关于无Move Semantics的swap函数拷贝次数的技术问询
为何无Move Semantics的swap实现会产生多次拷贝?
先看两个swap实现:
无Move Semantics的swap
template <class T> swap(T& a, T& b) { T tmp(a); // 此时存在两份a的拷贝 a = b; // 此时存在两份b的拷贝 b = tmp; // 此时存在两份tmp(即原a)的拷贝 }
带Move Semantics的swap
template <class T> swap(T& a, T& b) { T tmp(std::move(a)); a = std::move(b); b = std::move(tmp); }
你疑惑的核心是混淆了「参数传递的拷贝」和「构造/赋值操作的拷贝」——a和b确实是引用传递,这一步没有任何拷贝,但swap内部的构造和赋值操作才是产生拷贝的根源,逐行拆解如下:
T tmp(a);:这里调用T的拷贝构造函数,把a持有的数据完整复制一份到新对象tmp里。此时内存里同时存在原a和tmp两个独立实例,它们持有相同的数据,所以说「存在两份a的拷贝」。a = b;:这里调用T的拷贝赋值运算符,把b的数据复制到a的内存空间中。赋值完成后,原b和更新后的a都持有b的原始数据,因此此时有两份b的拷贝。b = tmp;:同样调用拷贝赋值运算符,把tmp(原a的拷贝)的数据复制到b的内存空间。现在tmp和更新后的b都持有原a的数据,自然就有两份原a的拷贝。
而带Move Semantics的版本,每一步用std::move把对象转换成右值,触发的是移动构造/移动赋值运算符——这些操作不会复制数据,只是把资源的所有权从一个对象转移到另一个(比如把指针从原对象移交到新对象,原对象变为空状态),所以全程没有额外拷贝,效率大幅提升。
内容的提问来源于stack exchange,提问作者Sergio Prieto
相关产品推荐
相关产品推荐

