C++中拷贝构造函数为何无需考虑半赋值问题?
为什么拷贝构造函数无需处理半赋值问题?
为避免拷贝赋值运算符出现半赋值问题(拷贝元素时抛出异常会导致目标对象处于新旧值混合状态),常用的「拷贝并交换」解决方案如下:
Matrix& Matrix::operator=(const Matrix& m) { Matrix tmp{m}; swap(tmp, *this); // 仅在拷贝成功后执行 return *this; }
二者的核心区别在于操作对象的状态完全不同:
拷贝赋值运算符操作的是已初始化完成的对象
赋值前,目标对象已经持有自己的资源(比如动态内存、文件句柄等)。如果直接在原对象上替换资源,中途抛出异常可能导致:部分资源已更新为新值、部分还是旧值,或者旧资源已释放但新资源创建失败,最终让对象陷入无效的「半赋值」状态。拷贝构造函数是从无到有创建新对象
构造过程中,对象本身还不存在——要么所有资源都初始化成功,构造函数正常返回,得到一个完全可用的新对象;要么构造中途抛出异常,此时不会有任何已完成初始化的对象遗留,所有临时分配的资源会被自动清理(比如栈上局部对象的析构、RAII资源的释放),不会留下一个「半拉子」的无效对象。
举个直白的例子:假设Matrix内部有动态数组int* data
- 若直接做赋值:先释放
this->data,再分配新内存拷贝数据,中途分配内存抛异常,this->data会变成空指针,对象彻底报废; - 若做拷贝构造:分配内存或拷贝数据时抛异常,正在构造的
tmp不会被创建出来,已分配的临时内存会被自动回收,不会留下有问题的对象。
内容的提问来源于stack exchange,提问作者rd142857
相关产品推荐
相关产品推荐

