自定义String类重载+运算符返回对象的C++错误问题
解决自定义String类重载+运算符返回新对象的问题
嘿,我帮你搞定这个自定义String类operator+的问题!看起来你应该是在参数类型、内存分配或者字符串复制环节出了疏漏,我给你梳理下问题根源和修正方案:
问题根源分析
你的operator+是const成员函数,但参数用了String & str,这意味着它没法接受const String对象或者临时对象;另外大概率是拼接时的内存计算(比如忘记给'\0'留位置)、字符串复制过程出错,导致新对象没有正确持有拼接后的内容。
修正方案与完整代码
第一步:修正operator+的参数类型
把参数改成const String& str,既符合const成员函数“不修改传入对象”的语义,也能兼容const对象和临时对象的传入。
第二步:正确处理内存分配与字符串拼接
要计算当前对象长度 + 传入对象长度 + 1(给终止符'\0'留位置),然后手动完成字符串的复制与追加(因为不能用标准库函数)。
下面是完整的可运行代码,分头文件和实现文件:
头文件(my_string.h)
#ifndef MY_STRING_H #define MY_STRING_H namespace MyStringNS { class String { private: char* m_data; size_t m_length; // 辅助函数:手动计算C风格字符串长度(替代标准库strlen) size_t calculateLength(const char* cstr) const { size_t len = 0; while (cstr[len] != '\0') { len++; } return len; } public: // 默认构造函数 String(const char* cstr = "") { m_length = calculateLength(cstr); m_data = new char[m_length + 1]; // 手动复制字符串(替代标准库strcpy) for (size_t i = 0; i <= m_length; i++) { m_data[i] = cstr[i]; } } // 拷贝构造函数 String(const String& other) { m_length = other.m_length; m_data = new char[m_length + 1]; for (size_t i = 0; i <= m_length; i++) { m_data[i] = other.m_data[i]; } } // 析构函数 ~String() { delete[] m_data; } // 重载赋值运算符 String& operator=(const String& other) { if (this != &other) { delete[] m_data; m_length = other.m_length; m_data = new char[m_length + 1]; for (size_t i = 0; i <= m_length; i++) { m_data[i] = other.m_data[i]; } } return *this; } // 修正后的+运算符重载 String operator+(const String& str) const; // 可选:重载+=运算符,比单独用+更高效(减少临时对象) String& operator+=(const String& str); // 获取C风格字符串指针 const char* c_str() const { return m_data; } // 获取字符串长度 size_t length() const { return m_length; } }; } // namespace MyStringNS #endif // MY_STRING_H
实现文件(my_string.cpp)
#include "my_string.h" namespace MyStringNS { String String::operator+(const String& str) const { // 计算拼接后的总长度(包含终止符的话要+1,这里先算内容长度) size_t totalContentLength = m_length + str.m_length; // 分配内存:内容长度 + 1(存储'\0') char* newData = new char[totalContentLength + 1]; // 复制当前对象的字符串到新数组 size_t i = 0; for (; i < m_length; i++) { newData[i] = m_data[i]; } // 追加传入字符串的内容 for (size_t j = 0; j < str.m_length; j++, i++) { newData[i] = str.m_data[j]; } // 必须添加字符串终止符 newData[totalContentLength] = '\0'; // 用新数组构造String对象 String result(newData); // 手动释放newData,因为构造函数已经复制了内容,避免内存泄漏 delete[] newData; return result; } // 可选的+=运算符实现(更高效) String& String::operator+=(const String& str) { size_t totalContentLength = m_length + str.m_length; char* newData = new char[totalContentLength + 1]; // 复制原有内容 size_t i = 0; for (; i < m_length; i++) { newData[i] = m_data[i]; } // 追加新内容 for (size_t j = 0; j < str.m_length; j++, i++) { newData[i] = str.m_data[j]; } newData[totalContentLength] = '\0'; // 释放原有内存,更新成员变量 delete[] m_data; m_data = newData; m_length = totalContentLength; return *this; } } // namespace MyStringNS
关键注意点
- 参数类型必须是const引用:否则const String对象没法参与加法运算,临时对象也传不进去。
- 内存分配要留足终止符位置:如果忘记给'\0'留位置,会导致字符串读取越界,出现未定义行为。
- 手动管理内存:operator+中分配的newData一定要手动释放,因为构造result时已经复制了内容,不释放会造成内存泄漏。
- 所有字符串操作都要手动实现:因为要求不能用标准库,所以长度计算、字符串复制都得自己写循环完成。
内容的提问来源于stack exchange,提问作者David Arico
相关产品推荐
相关产品推荐

