我读到过关于避免复制赋值操作符做半赋值的文章(它在复制项时抛出一些异常,所以赋值的目标变成新旧值混合的状态)。
Matrix& Matrix::operator=(const Matrix& m) { Matrix tmp{m}; swap(tmp, *this); // only be called when copy succeeds return *this; }
但是它首先调用了定制的复制构造函数,为什么复制构造函数不需要像复制赋值操作符那样检查半赋值呢?
jhdbpxl91#
当运行一个构造函数时,在构造函数中间抛出的异常不会破坏“先前的值”。这就是使用这个结构+swap作为赋值操作符的本质。任何异常都会在交换开始之前发生在ctor中,所以不会破坏被赋值对象的前一个值。
bttbmeg02#
因为C++会为你处理这个问题。如果成员的构造函数之一在成员初始化部分引发异常:任何已经构造的成员都会在抛出异常时被销毁(按照构造的相反顺序)。如果一个异常在构造函数中被抛出,所有的类成员都会自动被销毁(按照构造的相反顺序),作为抛出异常的一部分。如果在复制赋值的过程中抛出异常,那么没有魔法兔子可以从帽子里拉出来,可以在任何地方找到,可以将所有类成员恢复到复制赋值开始之前的状态。
2条答案
按热度按时间jhdbpxl91#
当运行一个构造函数时,在构造函数中间抛出的异常不会破坏“先前的值”。
这就是使用这个结构+swap作为赋值操作符的本质。任何异常都会在交换开始之前发生在ctor中,所以不会破坏被赋值对象的前一个值。
bttbmeg02#
因为C++会为你处理这个问题。
如果成员的构造函数之一在成员初始化部分引发异常:任何已经构造的成员都会在抛出异常时被销毁(按照构造的相反顺序)。如果一个异常在构造函数中被抛出,所有的类成员都会自动被销毁(按照构造的相反顺序),作为抛出异常的一部分。
如果在复制赋值的过程中抛出异常,那么没有魔法兔子可以从帽子里拉出来,可以在任何地方找到,可以将所有类成员恢复到复制赋值开始之前的状态。