2017-06-06 69 views
1

我已閱讀了一些關於移動功能的帖子(例如http://www.cprogramming.com/c++11/rvalue-references-and-move-semantics-in-c++11.html),並且我想觀察移動操作員的行動。所以,我想下面的代碼:C++ - NRVO和移動

#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; 
} 

我所期待的,因爲移動運營商的vector,能夠獲得相同的地址局部變量resultc。我得到了那個,但有和沒有國旗-std=c++11。那是當我瞭解到NRVO(c++11 Return value optimization or move?),所以我禁用了它的標誌-fno-elide-constructors,現在地址是不同的,即使是國旗-std=c++11。我的代碼存在問題,還是我理解移動操作員有什麼問題?

從我所瞭解的情況來看,按價值回報應該足以讓移動運營商踢出(C++11 rvalues and move semantics confusion (return statement))。

PS:我嘗試了GCC 6.3.0_1和Apple LLVM V8.1.0。

編輯

正如指出的那樣,我應該檢查result.data()而不是&result(見下文)。但在那種情況下,我總是找到相同的地址,即使沒有std=c++11-fno-elide-constructors。查看接受的答案及其評論部分。

回答

2

將移動看作優化副本。它仍然是一個副本,所以它仍然是一個不同的向量,但它將底層數據從一個向量「移動」到另一個向量。你可以看到,通過比較數據的地址:另一方面

cout<<result.data()<<endl; 

cout<<c.data()<<endl; 

複製省略完全消除副本。

+1

感謝您的快速回答。我用'數據'嘗試了,它工作。但是我也使用'-fno-elide-constructors'和'-std = C++ 11'獲得相同的地址。這很奇怪嗎?編譯器如何優化它,而不需要複製elision和移動操作符? –

+0

@PierreMarchand在你的問題,你說'-fno-的Elid-constructors'總是給不同的地址(這是我所期望的) –

+0

@MM我認爲他們指的。數據的'()' –

3

移動構造函數通過竊取舊構造函數的資源構造一個新對象。它根本不合並臨時對象:如果構造沒有被消除,你仍然有兩個對象。