c++使用字符串常量注意

关于 wstr 和 dir 的初始化及使用问题

在构造函数中你这样初始化 wstr 和 dir 并创建 YOCR 对象:

wstr = L"E:\\test\\test.EXE";
dir = L"E:\\test\\weisuoyuwei";
ocr = new YOCR(wstr, dir);

这里声明 wstr 和 dir 为 const wchar_t* 类型的成员变量,直接这样赋值宽字符字符串字面量给它们是不正确的做法哦。在 C++ 中,像 const wchar_t* 这样的指针类型,你不能简单地将字符串字面量直接赋值给它(虽然有些编译器可能不会立刻报错,但这不符合正确的语法和内存管理规则),实际运行调试,出现了wstr字符串识别出错的问题,但dir正常。

正确的做法应该是:

  1. 如果想使用字符串字面量初始化
    可以在类定义时就进行初始化(对于 const 成员变量来说更合适这种方式,这样保证它们一旦初始化就不可修改),像这样:
class Form1 {
public:
    Form1(QWidget* parent = nullptr, const char* name = nullptr, WFlags fl = 0);
    // 其他成员函数声明
private:
    // 其他成员变量声明
    const wchar_t* wstr = L"E:\\test\\test.EXE";
    const wchar_t* dir = L"E:\\test\\weisuoyuwei";
    YOCR* ocr;
    // 更多成员变量声明
};

这样在类实例化的时候,wstr 和 dir 就会自动初始化为指定的字符串字面量对应的宽字符字符串了,然后在构造函数里可以直接使用它们来创建 OCR 对象,如下:

Form1::Form1(QWidget* parent, const char* name, WFlags fl)
    : QMainWindow(parent, name, fl),
      ocr(new YOCR(wstr, dir))  // 直接使用初始化好的wstr和dir创建对象
{
    // 其他构造函数里的初始化代码保持不变,省略部分重复代码展示
    // (void)statusBar();
    if (!name)
        setName("Form1");
    setCentralWidget(new QWidget(this, "qt_central_widget"));
    // 后续初始化界面控件、设置布局、连接信号槽等代码不变
    //...
}
  1. 如果想在构造函数中动态分配内存并赋值字符串内容(不太推荐,但有时候有特殊需求可能这么做)
    你需要先为 wstr 和 dir 所指向的内存区域分配足够的空间,然后再将字符串内容复制进去,示例如下(这种方式相对复杂且要注意内存管理,避免内存泄漏等问题):
Form1::Form1(QWidget* parent, const char* name, WFlags fl)
    : QMainWindow(parent, name, fl)
{
    // 其他构造函数里的初始化代码保持不变,省略部分重复代码展示
    // (void)statusBar();
    if (!name)
        setName("Form1");
    setCentralWidget(new QWidget(this, "qt_central_widget"));

    // 为wstr分配内存并复制字符串内容
    size_t wstrLen = wcslen(L"E:\\test\\test.EXE") + 1;  // +1是为了包含字符串结束符'\0'
    wstr = new wchar_t[wstrLen];
    wcscpy_s(wstr, wstrLen, L"E:\\test\\test.EXE");

    // 为dir分配内存并复制字符串内容
    size_t dirLen = wcslen(L"E:\\test\\weisuoyuwei") + 1;
    dir = new wchar_t[dirLen];
    wcscpy_s(dir, dirLen, L"E:\\test\\weisuoyuwei");

    ocr = new YOCR(wstr, dir);

    // 后续初始化界面控件、设置布局、连接信号槽等代码不变
    //...

    // 记得在合适的地方(比如析构函数里)释放为wstr和dir分配的内存,避免内存泄漏,示例析构函数如下:
    // Form1::~Form1() {
    //     delete[] wstr;
    //     delete[] dir;
    //     // 其他清理资源的代码(如果有)
    // }
}

 这种方式需要手动管理内存,先通过 new 为 wstr 和 dir 分配了足够的内存空间(根据字符串长度计算,要包含字符串结束符 '\0'),然后使用 wcscpy_s(更安全的字符串复制函数,能避免一些缓冲区溢出问题)将字符串字面量的内容复制到分配好的内存区域中,最后用它们来创建 YOCR 对象。并且要记得在类的析构函数里释放这些动态分配的内存,防止内存泄漏哦。

  1. 动态获取字符串内容的情况
    • 当字符串的内容不是固定的常量,而是在运行时通过某种计算、用户输入或者从外部数据源(如网络、文件读取等)动态获取时,需要使用动态分配内存并复制字符串内容的方式。例如,如果wstr的内容需要根据用户在界面上的操作(如用户在另一个文本框中输入路径)或者根据程序从配置文件中读取的信息来确定,就不能使用简单的常量初始化。
    • 假设你有一个函数可以从配置文件中读取路径信息,返回一个std::wstring类型的路径(这里只是假设方便理解),你可以将其转换为wchar_t*并赋值给wstr。示例代码如下:
std::wstring getPathFromConfig() {
    // 这里是从配置文件读取路径并返回std::wstring类型路径的逻辑,假设已经实现
    std::wstring path = L"Some default path";
    // 实际应该是从配置文件读取路径并赋值给path的代码
    return path;
}

Form1::Form1(QWidget* parent, const char* name, WFlags fl)
    : QMainWindow(parent, name, fl)
{
    // 其他构造函数里的初始化代码保持不变,省略部分重复代码展示
    // (void)statusBar();
    if (!name)
        setName("Form1");
    setCentralWidget(new QWidget(this, "qt_central_widget"));

    std::wstring tempWstr = getPathFromConfig();
    size_t wstrLen = tempWstr.length() + 1;
    wstr = new wchar_t[wstrLen];
    wcscpy_s(wstr, wstrLen, tempWstr.c_str());

    // 对dir的初始化可以类似处理,如果也是动态获取的话

    ocr = new YOCR(wstr, dir);

    // 后续初始化界面控件、设置布局、连接信号槽等代码不变
    //...

    // 记得在合适的地方(比如析构函数里)释放为wstr和dir分配的内存,避免内存泄漏
}
  1. 需要修改字符串内容的情况(虽然对于const wchar_t*不太合适,但在某些特殊场景)

    • 如果在程序的后续部分,你需要对字符串内容进行修改(尽管const wchar_t*类型本意是指向不可修改的常量字符串,但有时候可能因为一些遗留代码或者特殊需求需要这样做),动态分配内存的方式可以提供这种灵活性。不过这种情况要谨慎使用,因为修改const类型指向的内容可能会导致未定义行为。
    • 例如,你可能有一个复杂的字符串处理逻辑,需要在程序运行过程中对路径字符串进行拼接、替换部分字符等操作。先动态分配内存可以方便后续的修改操作。但更好的做法是,如果需要修改字符串,应该使用std::wstring等支持修改操作的类型,在需要传递const wchar_t*类型时再进行转换。
  2. 内存管理的精细控制需求

    • 在一些对内存使用非常敏感的场景,如嵌入式系统或者内存受限的环境中,你可能需要精确地控制内存的分配和释放时机。动态分配内存可以让你在确切需要的时候分配所需的内存空间,并且在使用完后及时释放,避免不必要的内存占用。
    • 例如,如果你知道wstr所指向的字符串只会在某个特定的功能模块中使用,并且希望在这个功能模块结束后就立即释放内存,而不是等到整个程序结束或者对象析构时才释放,就可以采用这种动态分配内存的方式,并在合适的地方手动释放。但这种精细控制也增加了内存泄漏和悬空指针等错误的风险,需要谨慎处理。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值