关于c ++:将此指针指定给指针的rvalue引用

Assigning this pointer to rvalue reference to a pointer

下面的示例是否应编译?

1
2
3
4
5
6
7
8
9
10
11
12
struct B;
struct A
{
  A(B*&&){}
};

struct B : A
{
  B() : A(this){}
};

int main(){}

在包含clang的LWS上编译,但在gcc中我得到:

no known conversion for argument 1 from 'B* const' to 'B*&&'

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

我还想指出MSVC也错了:

cannot convert parameter 2 from 'B *const ' to 'B *&&'

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

虫子场

MSVC错误链接

GCC错误链接


是的,应该编译。

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

很多人认为,因为你不能修改this,它一定是const,但正如约翰内斯·沙乌布利特很久以前所评论的,一个更好的解释是这样的:

1
2
3
4
// by the compiler
#define this (__this + 0)

// where __this is the"real" value of this

这里很明显,你不能修改this(比如说,this = nullptr),但也很明显,这种解释不需要const。(您在构造函数中的值只是临时值。)


我说Clang是对的-代码应该编译。出于某种原因,GCC认为this指针是const,尽管有以下情况:

The type of this in a member function of a class X is X*. If the member function is declared const, the type of this is const X*, if the member function is declared volatile, the type of this is volatile X*, and if the member function is declared const volatile, the type of this is const volatile X*.

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

A reference to type"cv1 T1" is initialized by an expression of type"cv2 T2" as follows:

  • [...]

  • [...] or the reference shall be an rvalue reference.

    • If the initializer expression

      • is an xvalue, class prvalue, array prvalue or function lvalue and [...], or

      • has a class type (i.e., T2 is a class type), [...]

      then [...]

    • Otherwise, a temporary of type"cv1 T1" is created and initialized from the initializer expression using the rules for a non-reference copy-initialization (8.5). The reference is then bound to the temporary. [...]