首页 > 编程语言 >c++偶现问题备录

c++偶现问题备录

时间:2024-08-29 20:52:43浏览次数:11  
标签:std 备录 string c++ 偶现 QString str toStdString GString

目录

C++偶现问题备录

1. 偶现问题源码

源码示例如下:

class KZNCalculationException : public std::exception
{
public:
#ifdef KZN_LINUX
    KZNCalculationException(GString AMsg, GString AHit)
        : std::exception()
    {
        m_sMsg = AMsg;
        m_sHit = AHit;
    }
#else
    KZNCalculationException(GString AMsg, GString AHit)
        : std::exception(AMsg.toStdString().c_str())
    {
        m_sHit = AHit;
    }
#endif
    GString getHit()
    {
        return m_sHit;
    }
#ifdef KZN_LINUX
    virtual const char* what() const throw ()
    {
        return m_sMsg.toStdString().c_str();
    }
#endif

private:
    GString m_sHit;
#ifdef KZN_LINUX
    GString m_sMsg;
#endif
};

2. 问题根因分析

问题核心代码:m_sMsg.toStdString().c_str();

在Qt框架中,QString 是用于存储和操作Unicode字符串的类。当你需要将 QString 转换为标准C++字符串(即 std::string),以便与某些只接受C风格字符串(const char*)的API或函数交互时,你可能会遇到 QString.toStdString().c_str() 这样的表达式。下面我将详细解释这个表达式的含义和用法。

QString.toStdString()
QString.toStdString() 是 QString 类的一个成员函数,它返回一个 std::string 对象,该对象包含了与 QString 相同的字符序列,但编码为UTF-8(或系统默认的本地编码,这取决于Qt的配置和版本,但通常推荐和默认的是UTF-8)。这个转换是必需的,因为 QString 内部使用Unicode编码来存储字符串,而 std::string 通常用于存储以特定编码(如UTF-8)表示的字节序列。

std::string.c_str()
std::string.c_str() 是 std::string 类的一个成员函数,它返回一个指向以null结尾的字符数组(const char*)的指针,该数组包含了字符串的副本。这个指针指向的字符串是临时的,并且仅在调用 c_str() 的 std::string 对象存在期间有效。一旦 std::string 对象被销毁或修改,这个指针就可能指向无效的内存。

代码QString.toStdString().c_str() 的行为可能产生意外的结果,‌尤其是在处理临时字符串时。‌

在使用 QString::toStdString().c_str() 时,‌需要注意几个关键点:‌

  1. 临时字符串的问题:‌toStdString() 返回的是一个临时 std::string 对象。‌这个临时对象在调用 c_str() 时存在,‌但一旦 toStdString() 返回的 std::string 对象离开其作用域或被销毁,‌该临时对象也随之消失。‌因此,‌如果 c_str() 是在这个临时对象被销毁后调用的,‌返回的指针将指向一个无效的内存位置,‌这可能导致未定义的行为或程序崩溃。‌
  2. 避免的方法:‌为了避免上述问题,‌最佳实践是先将 QString 转换为 std::string,‌然后再调用该 std::string 的 c_str() 方法。‌这样做可以确保在调用 c_str() 时,‌std::string 对象仍然存在且有效。‌
  3. 特定环境的问题:‌在某些特定环境下,‌如 Windows 7 上使用 QString::toStdString() 可能会出现问题,‌尤其是在进行设备连接等操作时。‌这可能是因为操作系统或环境配置的不同导致的。‌

综上所述,‌虽然 QString::toStdString().c_str() 在某些情况下可能工作正常,‌但存在潜在的风险。‌开发者应当谨慎使用,‌并考虑上述提到的最佳实践,‌以确保代码的健壮性和稳定性。‌

3. 修复问题源码

3.1 修复方式一

class KZNCalculationException : public std::exception
{
public:
#ifdef KZN_LINUX
    KZNCalculationException(GString AMsg, GString AHit)
        : std::exception()
    {
        QByteArray ba = AMsg.toLocal8Bit();
        m_sMsg = new char[ba.size() + 1];
        strcpy(m_sMsg, ba.data());

        m_sHit = AHit;
    }
#else
    KZNCalculationException(GString AMsg, GString AHit)
        : std::exception(AMsg.toStdString().c_str())
    {
        m_sHit = AHit;
    }
#endif
    GString getHit()
    {
        return m_sHit;
    }
#ifdef KZN_LINUX
    virtual const char* what() const throw (){
           return m_sMsg;
    }
#endif
private:
    GString m_sHit;
#ifdef KZN_LINUX
    char * m_sMsg;
#endif
};

3.2 修复方式二

class KZNCalculationException : public std::exception
{
public:
#ifdef KZN_LINUX
    KZNCalculationException(GString AMsg, GString AHit)
        : std::exception()
    {
        m_sMsg = AMsg.toStdString();

        m_sHit = AHit;
    }
#else
    KZNCalculationException(GString AMsg, GString AHit)
        : std::exception(AMsg.toStdString().c_str())
    {
        m_sHit = AHit;
    }
#endif
    GString getHit()
    {
        return m_sHit;
    }
#ifdef KZN_LINUX
    virtual const char* what() const throw (){
           return m_sMsg.c_str();
    }
#endif
private:
    GString m_sHit;
#ifdef KZN_LINUX
    std::string m_sMsg;
#endif
};

标签:std,备录,string,c++,偶现,QString,str,toStdString,GString
From: https://www.cnblogs.com/Braveliu/p/18387539

相关文章

  • Qt | Qt是C++最好的图形界面开发库(学习路线图)
    点击上方"蓝字"关注我们01、WhatisQt?>>>Qt是一个跨平台的C++图形用户界面库,目前包括QtCreator、QtDesigner等等快速开发工具。Qt支持所有Linux/Unix系统,还支持windows平台。Qt很容易扩展,并且允许真正地组件编程。Qt与GTK、MFC、OWL、ATL 是一样的图形界......
  • C++基础面向对象特征
    目录学习目标:学习内容:1.C++对函数的扩充1.1函数重载(overload)1.1.1 概念1.1.2 要求1.2 函数的默认参数 1.3哑元 1.4内联函数        内联函数与带参宏的区别(重要)2.封装2.1面向对象的三大特质2.2C++中的类(class)2.3定义格式2.4 this指......
  • 【C++ Primer Plus习题】6.9
    问题:解答:#include<iostream>#include<string>#include<fstream>usingnamespacestd;typedefstruct_Donor{ stringname; doublemoney;}Donor;intmain(){ ifstreamfile; stringfilename; intcount=0; cout<<"请......
  • 【C++二分查找】2271. 毯子覆盖的最多白色砖块数
    本文涉及的基础知识点C++二分查找LeetCode2271.毯子覆盖的最多白色砖块数给你一个二维整数数组tiles,其中tiles[i]=[li,ri],表示所有在li<=j<=ri之间的每个瓷砖位置j都被涂成了白色。同时给你一个整数carpetLen,表示可以放在任何位置的一块毯子的长度......
  • 线程池ThreadPool, C++
    一、为什么要有线程池?线程池是一种用于管理和复用线程的机制。它可以提高程序的性能和效率,特别是在处理大量并发任务时。线程池中包含一定数量的线程,这些线程可以重复执行多个任务。当有任务需要执行时,可以将任务提交给线程池,线程池会选择一个可用的线程来执行任务。任务执行完......
  • c++1077-1081
    1077:地球人口承载力估计#include<iostream>#include<cstdio>usingnamespacestd;intmain(){inta,b,x,y;cin>>x>>a>>y>>b;doublez=0;z=(b*y-a*x)*1.0/(b-a);printf("%.2lf",z);return0;}1078......
  • C++学习——类当中static关键字的作用
    一、类和对象我们知道类是“行为”和“属性”的集合,我们可以通过类来实例化对象,从而定义对象的“行为”和“属性”。比如:classCar{ Stringbrand; Stringlicense; Stringcolor;}CarToyota;这里定义了“Car”的类,通过“Car”这个类实例化了“Toyota”。那么类当中的......
  • C++学习——访问修饰符
    一、类是什么类是C++当中的一个集合,定义了“属性”,通过类可以实例化对象,此时对象的属性就囊括在这个类当中。比如:classstudent{public: stringName; intages; stringgender}studentXiaoMin;上述代码定义了一个student类,并且通过这个类实例化了对象XiaoMin,XiaoMin......
  • C++火车头修订版
    #pragmaGCCoptimize(3)#pragmaGCCtarget("avx")#pragmaGCCoptimize("Ofast")#pragmaGCCoptimize("inline")#pragmaGCCoptimize("-fgcse")#pragmaGCCoptimize("-fgcse-lm")#pragmaGCCoptimize("-f......
  • 学习笔记3——栈(C++版)
     接下来教大家如何实现一个栈,我们采用单链表的形式。其实说白了就是给单链表写个入栈和出栈的函数就好了。和上一篇文章说的一样,这里说的栈和stack容器是不一样的。如何实现栈1.定义链表节点structStackNode{DataTypeval;ListNode*next;ListNode(DataTy......