C++中重载operator=后仍出现异常行为的问题排查
C++ Container类成员访问限制异常问题解析
定义了Container类,包含私有成员dataA_和dataB_(均为std::vector<int>),仅提供公开构造函数初始化dataA_,私有构造函数可同时初始化两个成员。重载拷贝赋值与移动赋值运算符时仅复制dataA_,以此限制外部访问dataB_。
但执行Container container2 = Container::func();时,container2的dataB_被填充,不符合预期;而container3 = container1;调用重载的赋值运算符,行为符合预期。
代码示例:
class Container { public: Container() = default; Container(const Container& vector) = delete; explicit Container(std::vector<int> data) : dataA_(std::move(data)) {} static Container func() { return Container(std::vector<int>(3,1), std::vector<int>(3,2)); } Container& operator=(const Container& other) { if (this != &other) { dataA_ = other.dataA_; } return *this; } Container& operator=(Container&& other) { if (this != &other) { dataA_ = std::move(other.dataA_); } return *this; } private: std::vector<int> dataA_; std::vector<int> dataB_; explicit Container(std::vector<int> dataA, std::vector<int> dataB) : dataA_(std::move(dataA)), dataB_(std::move(dataB)) {} }; int main() { std::cout << "init:" << std::endl; Container container1(std::vector<int>({1, 2, 3})); Container container2 = container1.func(); // 不符合预期 Container container3; container3 = container1; // 符合预期 return 0; }
原因分析
Container container2 = Container::func();是拷贝初始化操作,本质是调用构造函数而非赋值运算符。由于你仅显式删除了拷贝构造函数,但未定义或删除移动构造函数,编译器会自动生成一个默认的移动构造函数。- 默认移动构造函数的行为是将源对象的所有成员(包括
dataB_)进行移动,因此container2的dataB_会被func()返回对象的dataB_填充。 - 而
container3 = container1;是赋值操作,触发的是你重载的拷贝赋值运算符,该运算符仅处理dataA_,因此dataB_不会被修改,符合预期。
解决方法
要限制dataB_的传递,需要显式定义移动构造函数,仅对dataA_进行移动操作,dataB_保持默认构造的空状态:
修改后的Container类添加以下公开成员:
// 自定义移动构造函数,仅移动dataA_ Container(Container&& other) noexcept : dataA_(std::move(other.dataA_)) { // dataB_默认构造为空,不处理源对象的dataB_ }
添加自定义移动构造后,Container container2 = Container::func();会调用你定义的移动构造,dataB_保持空状态,符合预期。
内容的提问来源于stack exchange,提问作者fakl
相关产品推荐
相关产品推荐

