问题描述
有人可以解释为什么B不编译,但C吗?我不明白为什么std :: move是必需的,因为变量已经是一个右值引用。
Can someone explain why B doesn't compile, but C does? I don't understand why std::move is required since the variable is already an rvalue 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?
};
推荐答案
在语句中:
B(B&& b)
$ b b
参数 b
使用以下类型声明:rvalue引用 B
。
The parameter b
is declared with the type: rvalue reference to B
.
在语句中:
A(b)
表达式 b
是 B
类型的左值。
左值表达式不能绑定到右值引用:
And lvalue expressions can not bind to rvalue references: specifically the rvalue reference in the statement:
A(A&& a)
此逻辑与语言的其他部分完全一致。考虑此功能:
This logic follows cleanly from other parts of the language. Consider this function:
void
f(B& b1, B b2, B&& b3)
{
g(b1);
g(b2);
g(b3);
}
即使 f
所有声明为不同类型,表达式 b1
, b2
和 b3
都是类型 B
的左值表达式,因此都将调用相同的函数 g
无论 g
是否重载。
Even though the parameters of f
are all declared with different types, the expressions b1
, b2
and b3
are all lvalue expressions of type B
, and thus would all call the same function g
, no matter how g
is overloaded.
在C ++ 11中,变量的声明,以及使用该变量产生的表达式。和表达式从来没有引用类型。而是他们有一个值类别,正好是以下之一:lvalue,xvalue,prvalue。
In C++11 it is more important than ever to distinguish between a variable's declaration, and the expression that results from using that variable. And expressions never have reference type. Instead they have a value category of precisely one of: lvalue, xvalue, prvalue.
语句:
A(std::move(c))
是确定,因为 std :: move
返回一个右值引用。从返回右值引用的函数调用产生的表达式具有值类别:xvalue。和价值,xvalues被认为是价值。和类型 C
的右值表达式:
is ok, because std::move
returns an rvalue reference. The expression resulting from a function call returning an rvalue reference has value category: xvalue. And together with prvalues, xvalues are considered rvalues. And the rvalue expression of type C
:
std::move(c)
将绑定到右值引用参数: A(A&
will bind to the rvalue reference parameter in: A(A&& a)
.
我发现以下图表(最初由Bjarne Stroustrup发明)非常有用:
I find the following diagram (originally invented by Bjarne Stroustrup) very helpful:
expression
/ \
glvalue rvalue
/ \ / \
lvalue xvalue prvalue
这篇关于rvalue refs和std :: move的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!