2016-09-22 48 views
2

我有一個簡單的結構,它具有所有定義的構造函數。 它有一個int變量,每個構造函數和賦值運算符都輸出* this的地址,int的當前值和int的一個新值。 移動和複製賦值運算符和構造函數也會打印傳遞值的地址。通過值傳遞的附加移動構造函數

#include <iostream> 

struct X 
{ 
    int val; 
    void out(const std::string& s, int nv, const X* from = nullptr) 
    { 
     std::cout<<this<<"->"<<s<<": "<<val<<" ("<<nv<<")"; 
     if (from) 
      std::cout<<", from: ["<<from<<"]"; 
     std::cout<<"\n"; 
    } 

    X(){out("simple ctor X()",0); val = 0;} 
    X(int v){out("int ctor X(int)", v);val = v; } 
    X(const X& x){out("copy ctor X(X&)", x.val, &x);val = x.val; }; 
    X&operator = (const X& x){out("copy X::operator=()", x.val, &x); val = x.val; return *this;} 
    ~X(){out("dtor ~X", 0);} 
    X&operator = (X&& x){out("move X::operator(&&)", x.val, &x); val = x.val; return *this;} 
    X(X&& x){out("move ctor X(&&x)", x.val, &x);val = x.val;} 
}; 

X copy(X a){return a;} 

int main(int argc, const char * argv[]) { 
    X loc{4}; 
    X loc2; 
    std::cout<<"before copy\n"; 
    loc2 = copy(loc); 
    std::cout<<"copy finish\n"; 
} 

輸出:

0xffdf7278->int ctor X(int): 134523184 (4) 
0xffdf727c->simple ctor X(): 134514433 (0) 
before copy 
0xffdf7280->copy ctor X(X&): 1433459488 (4), from: [0xffdf7278] 
0xffdf7284->move ctor X(&&x): 1433437824 (4), from: [0xffdf7280] 
0xffdf727c->move X::operator(&&): 0 (4), from: [0xffdf7284] 
0xffdf7284->dtor ~X: 4 (0) 
0xffdf7280->dtor ~X: 4 (0) 
copy finish 
0xffdf727c->dtor ~X: 4 (0) 
0xffdf7278->dtor ~X: 4 (0) 

什麼是創建一個額外的對象(在這個例子中)地址0xffdf7284的目的是什麼?

回答

2

如果你看copy elision rules from cppreference.com,你可以注意到有兩種情況,即使複製/移動構造函數和析構函數具有可觀察的副作用,編譯器需要省略類對象的拷貝和移動構造函數,效果(由於打印輸出,您的操作)。第一個顯然與這種情況無關。第二種是

在函數調用中,如果return語句的操作數是prvalue,並且函數的返回類型與該prvalue的類型相同。

隨着給出的例子:

T f() { return T{}; } 
T x = f(); 

這似乎更具相關性,但是,請注意,在你的情況下,return聲明的操作數是不是prvalue。所以在這種情況下,沒有強制性的elision適用。

的一組步驟,主叫loc2 = copy(loc);時,如下:

  • a是拷貝構造從loc
  • 函數的返回值是從a移動構建的。
  • loc2是從返回值移動分配的。

從邏輯上講,一個人可以看代碼,並推斷出較少操作需要做的(尤其是看着copy時,很明顯的是,在邏輯上,從locloc2的分配就足夠了),但編譯器不知道您的代碼的目的不是產生副作用(打印輸出),並且這裏沒有違反任何規則。

+0

那麼,它被稱爲創建適當的價值? –

+0

@ Guy-WithA-gum沒有。由於它不是一個值,所有的方法都有副作用,所以它將它移出,然後調用析構函數。這根本不涉及prvalues。 –

+0

爲什麼它只是不返回「a」,爲什麼它需要從構建值中移走 –

相關問題