2012-03-14 195 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。