重载+=运算符结果不符合预期,自定义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".
排查引导
先自己思考几个关键点:
- +=运算符的核心语义是修改调用该运算符的对象本身,你的实现里有没有对
this指向的当前对象的成员变量做任何修改? - 当前实现最后返回的是局部对象
appendedObj的引用,这种操作会导致什么问题? - 类中的
string成员是const char*类型,你是否需要更新它的值来指向新拼接后的字符串? - 内存分配时,你申请的空间是否足够容纳拼接后的字符串加上终止符'\0'?
完整解决方案
问题根源
- 未修改原对象:你在operator+=中创建了新的StringF对象,但完全没有更新当前对象(
this)的string成员,原对象自然不会变化。 - 悬垂引用:返回局部对象
appendedObj的引用,该对象在函数结束后会被销毁,引用变为无效,属于未定义行为。 - 内存越界:分配内存时未给'\0'预留空间,
new char[stringLength + stringToAppendLength]的长度应该加1,否则写入appendedString[stringLength + stringToAppendLength] = '\0'会越界。 - 内存泄漏:如果原
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
相关产品推荐
相关产品推荐

