Const Rvalue引用捕获不应该可编译的重载

Const Rvalue reference to capture overloads which are not supposed to be compilable

本文关键字:编译 重载 不应该 Rvalue 引用 Const      更新时间:2023-10-16

Scott Meyers在44:15的演讲中表示,const Rvalue引用在c++0x标准库中用于捕获某些不可编译的重载。

说明上述要点的代码片段会很有帮助。谢谢

我发现有用的一个用法是禁用临时成员竞标引用成员。例如,考虑下面的代码:

struct Foo{};
class X
{
    const Foo& _foo;
public:    
    X(const Foo&&) = delete;       // prevents rvalue binding
    X(const Foo& foo): _foo(foo){} // lvalue is OK
};
Foo get_Foo()
{
    return {};
}
const Foo get_const_Foo()
{
    return {};
}
Foo& get_lvalue_Foo()
{
    static Foo foo;
    return foo;
}
int main() 
{
//  X x1{get_Foo()};        // does not compile, use of deleted function
//  X x2{get_const_Foo()};  // does not compile, use of deleted function
    X x3{get_lvalue_Foo()}; // OK
}

您肯定希望禁用传递给X构造函数的右值,因为右值不会通过构造函数参数绑定到const引用,所以您最终会得到一个悬空引用。为什么const Foo&&而不是简单的Foo&&?因为如果您使用X(Foo&&) = delete;,那么如果您的get_Foo()返回const Foo(这是一个坏主意,但在实际代码中可以看到),它将绑定到X(const Foo&),并且您最终会得到一个悬空引用。然而,上面代码中的X(const Foo&&)const Foo右值更好地匹配,因此我们获得了无法构造具有右值的X的期望效果。

您可能还会问,为什么不为左值构造函数定义X(Foo&)。那么您将无法绑定const lvalues。因此,最好的方法是标记X(const Foo&&) = delete;。希望这能澄清这一点。