【发布时间】:2019-01-23 02:00:17
【问题描述】:
我已经阅读了一些之前的热门答案以及 Stroustrup 的“The C++ Programming Language”和“Effective Modern C++”,但我很难真正理解表达式的左值/右值方面与其类型。在“Effective Modern C++”的介绍中说:
确定表达式是否为左值的一个有用的启发式方法是询问您是否可以获取其地址。如果可以,通常是这样。如果你不能,它通常是一个右值。这种启发式的一个很好的特性是它可以帮助您记住表达式的类型与表达式是左值还是右值无关......在处理右值引用类型的参数时记住这一点尤其重要,因为参数本身是一个左值。
我不理解某些东西,因为我不明白为什么如果您有一个右值引用类型参数,您需要通过std::move() 将其实际转换为右值以使其有资格被移动。即使参数(所有参数)是左值,编译器也知道它的类型是右值引用,那么为什么需要告诉编译器它可以移动呢?这似乎是多余的,但我想我不理解表达式的 类型 与其左值/右值性质之间的区别(不确定术语是否正确)。
编辑:
要跟进下面的一些答案/cmets,仍然不清楚的是为什么在下面的doSomething() 中我需要将参数包装在std::move() 中以使其绑定到右值引用并解析为doSomethingElse() 的第二版。我知道,如果这隐含地发生,那将是很糟糕的,因为该参数会被移出,并且在此之后可能会无意中使用它。看起来参数的右值引用类型性质在函数中是没有意义的,因为它的唯一目的是绑定以解析到函数的正确版本,因为右值作为参数传入。
Widget getWidget();
void doSomethingElse(Widget& rhs); // #1
void doSomethingElse(Widget&& rhs); // #2
void doSomething(Widget&& rhs) {
// will call #1
doSomethingElse(rhs);
// will call #2
doSomethingElse(std::move(rhs));
}
int main() {
doSomething(getWidget());
}
【问题讨论】:
-
这里似乎存在一些根本性的混淆; “引用”属于类型,左值/右值属于表达式。表达式永远不是引用,引用也永远不是表达式。左值引用绑定左值,右值引用绑定右值,这就是他们名字的意思。
-
@KerrekSB 其实没那么简单;以
const T&为例。 -
@LightnessRacesinOrbit: ...叹息,是的,当然,但首先近似。我想指出高层次的概念错误,而不用过多的细节混淆图片。
标签: c++ c++11 move move-semantics