c++:为什么调用 foo(X&) 而不是 foo(X&&)?

c++: why does foo(X&) get called instead of foo(X&&)?

本文关键字:foo c++ 为什么 调用      更新时间:2023-10-16

这里,creator()返回一个指向X的指针,我对其解引用并传递给foo。因为这是右值,所以应该使用move语义,对吧?但是当我运行它时,我发现foo(X&)被调用了。

#include <iostream>
using namespace std;
struct X {
        int i;
};
void foo(X& x) {
        cout << "foo(X&)" << endl;
}
void foo(X&& x) {
        cout << "foo(X&&)" << endl;
}
struct X* creator() {
        return new X {5};
}
main() {
        X x{5};
        foo(*creator()); // prints foo(X&)
}

creator()返回一个指针。

对该指针解引用将得到一个左值。指针解引用的结果是左值。毕竟,如果p是一个指针,你可以给它赋值:*p=some_value,你只能赋值给一个左值,因此它必须是一个左值。

你被两件事弄糊涂了。函数返回一个右值,这是真的。但是你没有传递函数的返回值。该函数返回一个指针,您对该指针解引用,结果是一个左值。

从同一性和可移动性的角度考虑问题是有帮助的:

  • 具有身份且无法移动?左值
  • 有身份,可以从?xvalue
  • 没有身份?prvalue

对指针进行解引用会产生一个具有标识的表达式,该标识不能被移动,因此它是一个左值。因此,它匹配X&过载。

如果你想调用另一个重载,你必须注释表达式,以表明它是安全的。这就是std::move的作用。一旦这样做,表达式就变成了一个xvalue,并且现在匹配X&&重载。