为std::vector启用移动语义是否需要按值传参避免元素拷贝?
你的思路方向是对的,但当前示例代码还缺关键的一步,无法实现你想要的「仅移动不拷贝」的效果。
问题原因
你现在的写法中,sourceData 是按值传入的参数:
- 当调用方传入右值(比如临时vector、经过
std::move处理的左值vector)时,sourceData确实会通过移动构造生成,不会触发拷贝 - 但你写的赋值语句
private_data_ = sourceData;里,sourceData是有明确名称的左值,编译器会默认调用拷贝赋值运算符,还是会拷贝元素
修正方案
只需要在赋值时加std::move 把参数转为右值,触发移动赋值即可:
#include <vector> #include <string> #include <utility> class data { public: void setMyData(std::vector<std::string> sourceData) { private_data_ = std::move(sourceData); // 新增std::move触发移动语义 } private: std::vector<std::string> private_data_; };
写法对比
这种「按值传参+内部移动」的写法,和写两个重载(左值引用版本+右值引用版本)的差异很小:
- 传入右值时:总开销是2次移动操作,和重载版本的1次移动操作差异极小,
std::vector的移动本身只需要交换内部指针,开销可以忽略 - 传入左值时:总开销是1次拷贝构造+1次移动,和左值引用重载版本的1次拷贝赋值开销基本一致
这种写法的优势是只需要维护一个函数,当函数有多个需要支持移动的参数时,能避免重载数量指数级增长,代码简洁很多。如果你对性能要求到了极致,也可以选择写两个重载版本:
// 左值版本:拷贝 void setMyData(const std::vector<std::string>& sourceData) { private_data_ = sourceData; } // 右值版本:移动 void setMyData(std::vector<std::string>&& sourceData) { private_data_ = std::move(sourceData); }
内容的提问来源于stack exchange,提问作者user1583007
相关产品推荐
相关产品推荐

