2012-03-14 197 views
-1

我在移動構造函數是新的,我從一些網站調查,並使用Visual Studio 11 Beta版快..試過移動構造函數和非常拷貝構造函數

下面是我的測試代碼...

#include <iostream> 

using namespace std; 

class Foo 
{ 
public: 
    Foo() 
     : Memory(nullptr) 
    { 
     cout<<"Foo Constructor"<<endl; 
    } 
    ~Foo() 
    { 
     cout<<"~Foo Destructor"<<endl; 
     if(Memory != nullptr) 
      delete []Memory; 
    } 
    Foo(Foo& rhs) 
     : Memory(nullptr) 
    { 
     cout<<"Copy Constructor"<<endl; 

     //allocate 
     //this->Memory = new .... 
     //copy 
     //memcpy(this->Memory, rhs.Memory...); 
    } 

    Foo& operator=(Foo& rhs) 
    { 
     cout<<"="<<endl; 
    } 
    void* Memory; 

    Foo(int nBytes) { Memory = new char[nBytes]; } 

    Foo(Foo&& rhs) 
    { 
     cout<<"Foo Move Constructor"<<endl; 
     Memory = rhs.Memory; 
     rhs.Memory = nullptr; 
    } 
}; 

Foo Get() 
{ 
    Foo f; 
    return f; 
    //return Foo(); 
} 
void Set(Foo rhs) 
{ 
    Foo obj(rhs); 
} 
int main() 
{ 
    Set(Get()); 
    return 0; 
} 

我不知道爲什麼它不會進入移動構造函數。

這真的是一個來自Get()的Rvalue;

如果我修改從常量構造非常拷貝構造函數,

將進入移動的構造。行爲改變...

任何人都可以解釋爲什麼發生了?

+5

'delete [] void_ptr;'是未定義的行爲。請注意'delete nullptr'完全正常,不需要事先檢查。另外,不需要所有無用的樣板代碼。剪下來,然後在問題中粘貼一個乾淨的例子。閱讀http://sscce.org。 – Xeo 2012-03-14 06:44:48

+0

噢,以及這個問題的答案:你最有可能[超過編譯器](http://ideone.com/wZEKF)(注意'g'中缺少構建副本,這是你的示例實際打印的內容) 。啓用優化後,編譯器會簡單地忽略所有這些移動/副本。 – Xeo 2012-03-14 06:54:05

+0

@Xeo:你的例子在'X f()'中缺少'return'。 – Mankarse 2012-03-14 06:55:54

回答

1
#include <iostream> 

using namespace std; 

class Foo 
{ 
public: 
    Foo(): 
     Memory(nullptr) 
    { 
     cout<< this << "Foo Constructor"<<endl; 
    } 

    ~Foo() 
    { 
     cout<< this << "~Foo Destructor"<<endl; 
     if(Memory != nullptr) 
      delete []Memory; 
    } 

    Foo(Foo& rhs) 
     :Memory(nullptr) 
    { 
     cout<<this << "Copy Constructor"<<endl; 

     //allocate 
     //this->Memory = new .... 
     //copy 
     //memcpy(this->Memory, rhs.Memory...); 
    } 

    Foo& operator=(Foo& rhs) 
    { 
     cout<<"="<<endl; 
    } 
    void* Memory; 

    Foo(int nBytes) { Memory = new char[nBytes]; } 

    Foo(Foo&& rhs) 
     { 
     cout<<this << "Foo Move Constructor"<<endl; 

       Memory = rhs.Memory; 


       rhs.Memory = nullptr; 
     } 

}; 

Foo Get() 
{ 
    Foo f; 
    cout << &f << "f" <<endl; 
    return f; 
} 

void Set(Foo rhs) 
{ 
    Foo obj(rhs); 
    cout << &obj << "obj"<<endl; 
} 

int main() 
{ 
    Set(Get()); 
    return 0; 
} 

輸出...

0x7fffe38fa0a0 Foo Constructor 
0x7fffe38fa0a0 f 
0x7fffe38fa070 Copy Constructor 
0x7fffe38fa070 obj 
0x7fffe38fa070 ~Foo Destructor 
0x7fffe38fa0a0 ~Foo Destructor 

答:由於命名返回值優化參數RHS被就地構建爲局部變量f的別名。 (也就是說rhs和f是同一個實例)。

作爲RHS是一個左值,複製構造用於複製從RHS構造OBJ。