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

自定义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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:25:25