我有以下代码:
#include<iostream>
using namespace std;
class A{
int size;
double *arr;
public:
A(int len):size(len)
{
cout<<"ctor called"<<endl;
arr=new double[size];
}
A(const A &rhs)
{
cout<<"calling copy ctor"<<endl;
size=rhs.size;
arr=new double[size];
}
A(A&& rhs)
{
cout<<"caling move constructor"<<endl;
size=rhs.size;
arr=rhs.arr;
rhs.arr=nullptr;
}
~A()
{
cout<<"Calling Dtor"<<endl;
delete[] arr;
size=0;
arr=NULL;
}
};
A createVector()
{
cout<<"Creating object"<<endl;
A a(20);
cout<<"returning after creating object a"<<endl;
return (a);
}
void foo(A v)
{
cout<<"Class A object rcvd"<<endl;
return;
}
int main()
{
//cout<<"a has been rcvd"<<endl;
foo(createVector());
return 0;
}
我已经传递了一个'A'类型的临时对象(已由另一个函数返回)。我期望调用Move构造函数,但是我得到以下输出:
Creating object
ctor called
returning after creating object a
Class A object rcvd
Calling Dtor
为什么不调用Move Constructor? 同样,如果更改代码如下:
foo(createVector())----->foo(move(createVector()));
我得到以下输出:
Creating object
ctor called
returning after creating object a
caling move constructor
Class A object rcvd
Calling Dtor
Calling Dtor
为什么两次调用Destructor?
答案 0 :(得分:2)
为什么不调用Move构造函数?
由于对移动进行了优化,因此无需调用move构造函数。 createVector
创建其A
对象时,通常不会在本地变量中创建对象。而是在通常的位置为返回值创建对象。此返回值到达main
为其指定的位置,即其“类型'A'的临时对象”。由于此临时变量是通过值传递给另一个函数的,因此通常在此类参数处构造它。
因此,当createVector
创建其名为A
的{{1}}对象时,a
的位置已经是a
传递给{ {1}},不需要移动(直到您明确请求移动)。麾!您的编译器效率很高!忽略它,继续关注更重要的问题。 (如果这不仅仅是尝试理解移动语义,那么您可能正在编写错误的代码。)
为什么两次调用Destructor?
因为您强迫两个对象存在。在这种情况下,由main
返回的临时对象被强制放置在与用作foo
参数的对象不同的位置。两者都需要销毁。 (从对象移开可能会使该对象处于无法使用的状态,但仍然是一个需要销毁的对象。无法使用的状态的确必须具有足够的一致性以使析构函数能够处理。)