有人能解释一下为什么B不能编译,而C可以吗?我不明白为什么需要std::move,因为变量已经是一个右值ref了。
struct A {
int x;
A(int x=0) : x(x) {}
A(A&& a) : x(a.x) { a.x = 0; }
};
struct B : public A {
B() {}
B(B&& b) : A(b) {} // compile error with g++-4.7
};
struct C : public A {
C() {}
C(C&& c) : A(std::move(c)) {} // ok, but why?
};发布于 2012-04-20 07:24:22
在声明中:
B(B&& b)参数 b使用类型: rvalue引用到B来声明。
在声明中:
A(b)expression b是B类型的左值。
左值表达式不能绑定到右值引用:特别是语句中的右值引用:
A(A&& a)这一逻辑从语言的其他部分清晰地遵循下来。考虑这个函数:
void
f(B& b1, B b2, B&& b3)
{
g(b1);
g(b2);
g(b3);
}尽管f的参数都是用不同的类型声明的,但表达式b1、b2和b3都是B类型的左值表达式,因此无论g如何重载,都会调用相同的函数g。
在C++11中,区分变量的声明和使用该变量所产生的表达式比以往任何时候都更加重要。并且表达式永远不会有引用类型。相反,它们的值类别恰好是: lvalue,xvalue,prvalue之一。
声明:
A(std::move(c))是可以的,因为std::move返回一个右值引用。函数调用返回右值引用所产生的表达式具有值category: xvalue。与prvalue一起,xvalue被认为是rvalue。和C类型的右值表达式
std::move(c)将绑定到:A(A&& a)中的右值引用参数。
我发现下面的图表(最初是由Bjarne Stroustrup发明的)非常有用:
expression
/ \
glvalue rvalue
/ \ / \
lvalue xvalue prvalue发布于 2012-04-20 06:53:14
因为命名变量不是右值,即使声明了&&。如果它有一个名字,那么它就不是临时的,因此你需要使用std::move。
https://stackoverflow.com/questions/10237971
复制相似问题