使用 *this 从右值进行的预期无效初始化

Intended invalid intialization from rvalue using *this

在 C++ 中,不可能将右值参数绑定到非 const 左值引用。但我注意到,当我调用 r 值对象时,返回 *this 的方法会以某种方式编译。

示例: 显然这段代码不会编译

    class X
    {
    };
    
    void bar(X&)
    {
    }

    int main()
    {
      foo(X{}); //  invalid initialization of non-const reference of type 'X&' from an rvalue of type 'X'
    }

但是向 X 添加一个简单的方法使其可编译:

class X
{
   public:
   X& foo() { return *this; }  
};

void bar(X&)
{
}

int main()
{
  bar(X{}.foo());
}

为什么有效?是不是说调用foo后右值对象变成了左值对象?使用这样的结构安全吗?有没有其他方法可以在不创建新方法的情况下实现类似的效果(类似于 X.this)?

如评论中所述,foo returns 是左值,而不是右值,因此将其传递给 bar 就可以了。

如果 X{}.foo() returns 一个左值感觉很奇怪,即使 X{} 本身是一个右值,请将 foo() 视为一个函数(隐含地)接受 this 和 returns 某物(恰好是 this 指向的东西)通过左值引用。现在,foo 怎么取 this?它接受右值吗?它接受左值吗?两者都是,但你可以编写只允许一种用法的东西(寻找 ref-qualified 成员函数 here):

class X
{
   public:
   X& fool() &  { return *this; } // called on lvalue objects
   X& foor() && { return *this; } // called on rvalue objects
};

void bar(X&)
{
}

int main()
{
    X x;
  bar(x.fool());
  //bar(x.foor());   // fails
  //bar(X{}.fool()); // fails
  bar(X{}.foor());
}

不过,注意你的做法:

#include <iostream>
#include <type_traits>
class X
{
   public:
   X& fool() &  { return *this; }
   X& foor() && { return *this; }
   ~X() { std::cout << "dtor\n"; }
};

void bar(X&)
{
}

int main()
{
  auto& xxx = X{}.foor();
  // use xxx, but X{} has been destroyed
  std::cout << "bye\n";
}