You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义C++ String类赋值时旧内存检查未执行问题排查

问题根源:混淆了构造函数调用与赋值操作

嘿,你忽略了一个关键的C++基础概念:构造函数只会在对象初始化的时候被调用,而msg = "Hello";是对一个已经存在的对象执行赋值操作,根本不会触发你写的那个带const char*参数的构造函数!

具体发生了什么?

  1. String msg;阶段:这是对象初始化,正确调用了默认构造函数,此时msg.str指向了你分配的1字节内存,确实是非NULL的。
  2. msg = "Hello";阶段:这是赋值操作,不是初始化。因为msg已经存在,C++会做两件事:
    • 首先,把字符串字面量"Hello"隐式转换成一个临时的String对象(这时候会调用你写的带const char*的构造函数,但这个临时对象的str初始是NULL,所以它的if (str != NULL)分支也不会执行);
    • 然后,调用编译器自动生成的默认拷贝赋值运算符,把临时对象的len和str直接拷贝给msg。

这就导致:你原本期望在赋值时释放msg旧内存的逻辑完全没被执行,反而因为默认赋值的浅拷贝,最后还会导致内存泄漏(msg原来的内存没被释放,现在又指向了临时对象分配的内存,临时对象销毁后还可能出现野指针问题)。

你的构造函数还有额外问题

顺便提一句:你写的带const char*参数的构造函数里,if (str != NULL)的判断完全没用!因为构造函数是用来创建新对象的,类成员的默认初始化char *str = NULL;会在构造函数体执行前完成,所以这个构造函数里的str一开始就是NULL,这个分支永远不会进入。而且构造新对象时根本不需要释放内存,因为还没分配过,这个判断属于画蛇添足。

如何修正?

你需要自己重载赋值运算符,把你期望的内存释放/重新分配逻辑放在这里:

class String {
public:
    int len;
    char *str = NULL;
    // Default constructor
    String() {
        len = 0;
        str = new char[1];
        str[0] = '\0';
        printf("New memory: %p\n", str);
    }
    // Constructor from const char*
    String(const char *ch) {
        len = strlen(ch);
        // 这里不需要检查str,因为是新对象,str初始为NULL
        str = new char[len + 1];
        printf("New memory: %p\n", str);
        strcpy(str, ch); // 用strcpy更简洁,和你的循环效果一致
    }

    // 重载赋值运算符,处理const char*的赋值
    String& operator=(const char* ch) {
        // 先释放旧内存
        if (str != NULL) {
            printf("Old memory: %p\n", str);
            delete[] str; // 注意用delete[],因为是new[]分配的!
            printf("Deleted...\n");
        }
        // 重新分配内存并拷贝内容
        len = strlen(ch);
        str = new char[len + 1];
        printf("New memory: %p\n", str);
        strcpy(str, ch);
        return *this;
    }

    // 别忘了添加析构函数,防止内存泄漏!
    ~String() {
        if (str != NULL) {
            delete[] str;
        }
    }
};

关键要点总结

  • 区分初始化(String msg("Hello");或String msg = "Hello";)和赋值(msg = "Hello";):前者调用构造函数,后者调用赋值运算符。
  • 动态分配内存的类,必须手动重载赋值运算符(以及拷贝构造函数,不然浅拷贝会出问题),还要写析构函数释放内存——这就是C++的三大法则(Rule of Three)。
  • 用new[]分配的内存,必须用delete[]释放,不能用delete,否则会有未定义行为。

内容的提问来源于stack exchange,提问作者Next-93

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 15:23:12