我已经阅读了一些关于移动函数的帖子(例如http://www.cprogramming.com/c++11/rvalue-references-and-move-semantics-in-c++11.html),我想观察移动运算符的运行情况。所以我尝试了以下代码:
ng build --base-href
我期望为局部变量#include <vector>
#include <cassert>
#include <functional>
#include <algorithm>
#include <iostream>
using namespace std;
vector<double> operator+(const vector<double>& a, const vector<double>& b){
assert(a.size()==b.size());
vector<double> result(a.size(),0);
transform (a.begin(), a.end(), b.begin(), result.begin(), std::plus<double>());
cout<<&result<<endl;
return result;
}
int main(int argc, char const *argv[]) {
vector<double> a,b;
for (int i=0;i<10;i++){
a.push_back(i);
b.push_back(1);
}
std::vector<double> c=a+b;
cout<<&c<<endl;
return 0;
}
和result
获取相同的地址,因为移动运算符是为c
实现的。而且我获得了这个,但有和没有标志vector
。那时我学习了NRVO(c++11 Return value optimization or move?),所以我用标志-std=c++11
禁用它,现在地址不同,即使标志为-fno-elide-constructors
。我的代码是否存在问题,或者我对移动运算符有什么不妥?
根据我的理解,按值返回应足以让移动操作员启动(C++11 rvalues and move semantics confusion (return statement))。
PS:我尝试使用GCC 6.3.0_1和Apple LLVM版本8.1.0。
修改
正如所指出的那样,我应该检查-std=c++11
而不是result.data()
(见下文)。但在这种情况下,我总是找到相同的地址,即使没有&result
和std=c++11
也是如此。请参阅已接受的答案及其评论部分。
答案 0 :(得分:3)
移动构造函数通过窃取旧对象的资源来构造新对象。它根本不合并临时工具:如果构造没有被省略,你仍然有两个对象。
答案 1 :(得分:2)
将移动视为优化副本。它仍然是一个副本,所以它仍然是一个不同的向量,但它有&#34;移动&#34;从一个向量到另一个向量的基础数据。您可以通过比较数据的地址来看到:
cout<<result.data()<<endl;
和
cout<<c.data()<<endl;
另一方面,复制省略完全取消了复制品。