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

operator+重载出现意外副作用,如何正确实现无副作用的operator+?

正确实现无副作用的C++ operator+运算符

你的问题出在operator+的实现违反了C++运算符的常规语义:你让它返回当前对象的引用,并且直接修改了this指向的原对象(也就是代码里的b1),这才导致原有对象被意外修改。

要实现无副作用的operator+,需要遵循两个核心原则:

  • operator+应该生成并返回新对象,而不是修改原有操作数
  • 成员函数版本的operator+必须声明为const,保证不会修改当前对象

修正后的实现方案

方式一:直接实现无副作用的operator+

修改operator+的返回类型和实现逻辑,先复制当前对象的内容到新对象,再合并另一个书架的书籍,最后返回新对象:

#include <iostream>
#include <string>
#include <vector>

using namespace std;

class BookShelf
{
    vector<string> m_books;

public:
    BookShelf(const vector<string>& books)
        : m_books(books)
    {
    }

    // 修正后的operator+:返回值为对象,且成员函数声明为const
    BookShelf operator+(const BookShelf& bookshelve) const
    {
        // 先创建当前对象的副本
        BookShelf result = *this;
        // 把另一个书架的书籍加到副本中
        for (const auto& b : bookshelve.m_books)
            result.m_books.push_back(b);
        // 返回新对象
        return result;
    }

    void print()
    {
        for (const auto& book : m_books)
            cout << book << " ";
        cout << endl;
    }
};

int main()
{
    BookShelf b1{{"abc", "def"}};
    b1.print();

    BookShelf b2{{"ghi", "jlm", "nop"}};
    b2.print();

    BookShelf b3 = b1 + b2;
    b3.print();

    b1.print(); // 现在b1不会被修改,输出原始内容
    b2.print();
}

方式二:基于operator+=实现operator+(更推荐)

按照C++的惯例,通常先实现operator+=(负责修改当前对象),再基于它实现operator+,这样代码更复用,也符合运算符的语义分工:

// 在类中先实现operator+=
BookShelf& operator+=(const BookShelf& rhs)
{
    for (const auto& b : rhs.m_books)
        m_books.push_back(b);
    return *this;
}

// 再实现operator+,利用operator+=完成合并
BookShelf operator+(const BookShelf& rhs) const
{
    BookShelf result = *this;
    result += rhs;
    return result;
}

运行结果验证

修正后运行代码,会得到符合预期的结果:

abc def 
ghi jlm nop 
abc def ghi jlm nop 
abc def 
ghi jlm nop 

此时b1保持原始状态,只有新对象b3是合并后的结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 06:35:20