将此指针赋值给指针的右值引用

Assigning this pointer to rvalue reference to a pointer

本文关键字:指针 引用 赋值      更新时间:2023-10-16

下面的示例应该编译吗?

struct B;
struct A
{
  A(B*&&){}
};
struct B : A
{
  B() : A(this){}
};
int main(){}

在LWS上使用clang可以编译,但是使用gcc我得到:

实参1没有从'B* const'到'B*&&'的已知转换

如果我添加一个const,它会编译。

我还想指出MSVC也犯了错误:

无法将形参2从'B *const '转换为'B *&&'

所以看起来我们在两个编译器中有一个错误

bug提交

MSVC bug link

是的,应该可以编译。

this实现为cv T* const是不正确的(其中cv是函数的cv限定符,如果有的话,T是类类型)。this不是const,它只是一个内置类型的右值表达式(不可修改)。

许多人认为,因为你不能修改this,所以一定是const,但正如Johannes Schaub - litb很久以前评论的那样,一个更好的解释是这样的:

// by the compiler
#define this (__this + 0)
// where __this is the "real" value of this

这里很明显,您不能修改this(例如this = nullptr),但也很清楚,对于这样的解释,没有const是必要的。(构造函数中的值就是临时变量的值)

我说clang是对的——代码应该可以编译。由于某些原因,GCC认为this指针是const,尽管有以下规定:

X的成员函数中this的类型为X*。如果成员函数声明为const,则this的类型为const X*;如果成员函数声明为volatile,则this的类型为volatile X*;如果成员函数声明为const volatile,则this的类型为const volatile X*

所以在这种情况下,this应该是一个右值B*,并与B*&&完全绑定。但是,请注意,当将this绑定到右值引用时,this的值将被复制到一个临时对象中,而引用将被绑定到该对象。这可以确保您永远不会实际修改原始this值。

对类型"cv1 T1"的引用由类型"cv2 T2"的表达式初始化,如下所示:

  • […]

  • […]或引用必须是右值引用

    • 如果初始化表达式

      • 是一个xvalue,类的右值,数组的右值或函数的左值和[…]),或者

      • 有一个类类型(例如,T2是一个类类型 ), [...]

      然后[…]

    • 否则,使用非引用复制初始化的规则从初始化表达式创建并初始化类型为"cv1 T1"的临时对象。然后将引用绑定到临时对象。[…]