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

重载+=运算符结果不符合预期,自定义StringF类问题排查

自定义StringF类重载+=运算符后原对象未更新的问题

我为学习目的编写了自定义StringF字符串类,尝试重载+=运算符实现字符串追加功能,但调用该运算符后初始对象并未发生改变。期望执行测试代码后,s输出"Hello, World!",但实际仍输出"Hello"。

相关代码

operator+=实现代码

StringF& StringF::operator+=(StringF& obj) {
    const char* string = this->getString();
    const char* stringToAppend = obj.getString();

    const int stringLength = this->length();
    const int stringToAppendLength = obj.length();

    char* appendedString = new char[stringLength + stringToAppendLength];
    appendedString[stringLength + stringToAppendLength] = '\0';


    for (int i = 0; i < stringLength; i++) {
        appendedString[i] = string[i];
    }

    for (int i = stringLength; i < stringLength + stringToAppendLength; i++) {
        appendedString[i] = stringToAppend[i - stringLength];
    }

    StringF appendedObj = StringF::StringF(appendedString);

    std::cout << "Appended obj: " << appendedObj.getString() << std::endl; //For debugging

    return appendedObj;
}

类头文件代码

class StringF {
    private:
        const char* string;
    public:
        StringF(const char*);
        int length();
        const char* copy();
        const char* getString();
        const char* reverse();
        int find(const char*);
        StringF& operator+=(StringF&);
        friend std::ostream& operator<<(std::ostream&, StringF&);
};

测试代码

StringF s("Hello");
StringF s2(", World!");
s += s2;
std::cout << s << std::endl; //Should print "Hello, World!" but only prints "Hello".

排查引导

先自己思考几个关键点:

  1. +=运算符的核心语义是修改调用该运算符的对象本身,你的实现里有没有对this指向的当前对象的成员变量做任何修改?
  2. 当前实现最后返回的是局部对象appendedObj的引用,这种操作会导致什么问题?
  3. 类中的string成员是const char*类型,你是否需要更新它的值来指向新拼接后的字符串?
  4. 内存分配时,你申请的空间是否足够容纳拼接后的字符串加上终止符'\0'?

完整解决方案

问题根源

  1. 未修改原对象:你在operator+=中创建了新的StringF对象,但完全没有更新当前对象(this)的string成员,原对象自然不会变化。
  2. 悬垂引用:返回局部对象appendedObj的引用,该对象在函数结束后会被销毁,引用变为无效,属于未定义行为。
  3. 内存越界:分配内存时未给'\0'预留空间,new char[stringLength + stringToAppendLength]的长度应该加1,否则写入appendedString[stringLength + stringToAppendLength] = '\0'会越界。
  4. 内存泄漏:如果原string是动态分配的,需要先释放旧内存,再赋值新内存。

修正后的operator+=代码

StringF& StringF::operator+=(StringF& obj) {
    const char* originalStr = this->getString();
    const char* appendStr = obj.getString();

    int originalLen = this->length();
    int appendLen = obj.length();

    // 分配足够的内存:原长度+追加长度+1(存'\0')
    char* newStr = new char[originalLen + appendLen + 1];
    
    // 复制原字符串
    for (int i = 0; i < originalLen; i++) {
        newStr[i] = originalStr[i];
    }
    // 复制追加的字符串
    for (int i = 0; i < appendLen; i++) {
        newStr[originalLen + i] = appendStr[i];
    }
    // 添加终止符
    newStr[originalLen + appendLen] = '\0';

    // 释放原对象的旧内存(假设构造函数中是动态分配的string)
    delete[] originalStr;
    // 更新当前对象的string成员
    this->string = newStr;

    // 返回当前对象的引用,符合+=的语义
    return *this;
}

补充说明

  • 确保你的StringF构造函数是动态分配内存给string成员,否则delete[] originalStr会出错。
  • 如果构造函数只是直接赋值传入的const char*(比如指向字符串字面量),需要调整内存管理逻辑,避免释放字面量导致崩溃。

内容的提问来源于stack exchange,提问作者Darawan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 20:25:56