这是我的班级和我的课程:
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
能够使用移动构造函数,但我得到的输出是:
A a - &gt;默认ctor。
A b(A()) - &gt;
A c(a.f()) - &gt;复制ctor。
A d(a.g()) - &gt;复制ctor。
A e(A()。g()) - &gt;默认ctor。复制ctor。
如果在所有三种情况下r值都是构造函数的参数,为什么不使用移动构造函数?
显然我正在使用-std=c++11
选项进行编译。
答案 0 :(得分:4)
使用b
,您已点击“most vexing parse”。 b
是一个函数声明,而不是一个对象。
采用表达式
A b(A());
让我们做一些名称更改和语义保留转换:
int foo(int (*p)());
现在,我认为很明显foo
是一个函数(返回int
并将int()
函数指针作为参数)。现在将A
替换为int
,将b
替换为foo
并记住函数隐式转换为指向函数的指针。你会看到它是一样的。
为了解决这个问题,你可以使用大括号初始化(感谢@MikeSeymour指出这一点):
A b{A()};
使用d
,我认为你是copy elision的“受害者”。 “copy ctor”输出可能是用*this
初始化返回值;从返回值到d
的移动完全被忽略了。
使用e
,它与d
的故事相同。