我读过一些之前的最佳答案以及 Stroustrup 的“C++ 编程语言”和“Effective Modern C++”,但我很难真正理解表达式的左值/右值方面与其类型之间的区别。在《Effective Modern C++》的简介中说:
确定表达式是否为左值的一个有用的启发式方法是询问是否可以获取其地址。如果可以的话,通常是这样。如果不能,它通常是一个右值。这种启发式的一个很好的功能是,它可以帮助您记住表达式的类型与表达式是左值还是右值无关......在处理右值引用类型的参数时记住这一点尤其重要,因为参数本身是一个左值。
我不明白一些事情,因为我不明白为什么如果你有一个右值引用类型参数,你需要通过以下方式将其实际转换为右值:std::move()
使其有资格被移动。即使参数(所有参数)是左值,编译器也知道其类型是右值引用,那么为什么需要告诉编译器它可以移动呢?这似乎是多余的,但我想我不明白两者之间的区别type表达式及其左值/右值性质(不确定正确的术语)。
Edit:
为了跟进下面的一些答案/评论,仍然不清楚的是为什么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());
}
我不明白为什么如果你有一个右值引用类型参数,你需要通过以下方式将其实际转换为右值std::move()
使其有资格被移动。
正如引文所说,types https://en.cppreference.com/w/cpp/language/type and 价值类别 https://en.cppreference.com/w/cpp/language/value_category是不同的东西。参数始终是左值,即使其类型是右值引用;我们必须使用std::move
将其绑定到右值引用。假设我们允许编译器隐式执行此操作,如以下代码片段所示,
void foo(std::string&& s);
void bar(std::string&& s) {
foo(s);
// continue to use s...
// oops, s might have been moved
foo(std::string{}); // this is fine;
// the temporary will be destroyed after the full expression and won't be used later
}
所以我们必须使用std::move
明确地告诉编译器我们知道我们要做什么。
void bar(std::string&& s) {
foo(std::move(s));
// we know that s might have been moved
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)