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
相关产品推荐
相关产品推荐

