这是我的类和程序:
class A {
public:
int x;
int* v;
A() : x(5), v(new int[5]) {cout<<"default ctor. "; for (int i=0; i<x; i++) v[i]=rand()%10;}
A(const A& a) : x(a.x), v(new int[x]) {cout<<"copy ctor. "; for (int i=0; i<x; i++) v[i]=a.v[i]; }
A(A&& a) : x(a.x), v(a.v) {cout<<"move ctor. ";a.x=0;a.v=0;}
A& f() {return *this;}
A g() {return *this;}
};
int main() {
srand(time(0));
cout<<"A a --> ";A a;cout<<endl;
cout<<"A b(A()) --> ";A b(A());cout<<endl;
cout<<"A c(a.f()) --> ";A c(a.f());cout<<endl;
cout<<"A d(a.g()) --> ";A d(a.g());cout<<endl;
cout<<"A e(A().g()) --> ";A e(A().g());cout<<endl;
}
我希望对象b
、d
和e
使用move构造函数,但我得到的输出是:
一个-->默认ctor。
A b(A())-->
一个c(A.f())-->复制ctor。
一个d(A.g())-->复制ctor。
一个e(A().g())-->默认ctor。复制ctor。
如果在这三种情况下,r值都是构造函数的参数,为什么不使用move构造函数?
显然,我使用-std=c++11
选项进行编译。
使用b
,您已经达到了"最麻烦的解析"。b
是一个函数声明,而不是对象。
取表达式
A b(A());
让我们做一些名称更改和语义保留转换:
int foo(int (*p)());
现在,我认为很清楚foo
是一个函数(返回int
并将指向int()
函数的指针作为参数)。现在用A
代替int
,用b
代替foo
,记住函数被隐式转换为指向函数的指针。你会发现这是一样的。
为了解决这个问题,你可以使用大括号初始化(感谢@MikeSeymour指出了这一点):
A b{A()};
对于d
,我认为您是拷贝省略的"受害者"。"copy ctor"输出可能来自于用*this
初始化返回值;从返回值到CCD_ 16的移动被完全消除。
有了e
,情况就和d
一样了。