问题 将此指针指定给指针的右值引用


以下示例应编译吗?

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 * &&'

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

BUGS FILED

MSVC错误链接

GCC错误链接


6630
2018-03-21 21:36


起源

有关信息 - 这是在英特尔C ++编译器(13.1)上编译的 - teppic


答案:


是的,那应该编译。

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

很多人认为因为你无法修改 this 一定是 const但是作为 Johannes Schaub - litb 很久以前评论过,更好的解释是这样的:

// by the compiler
#define this (__this + 0)

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

这里显然你无法修改 this (说, this = nullptr),但也清楚没有 const 这样的解释是必要的。 (而你在构造函数中的值只是临时值。)


8
2018-03-21 21:50



是否实际指定我们无法修改 this?显然我们不能当它是一个prvalue,但如果我们将它绑定到右值引用并通过它修改它会怎样? - Joseph Mansfield
有意思,这意味着 这个SO问题的选定答案 是错的? - Jesse Good
@GManNickG我已经弄清楚了。将右值引用绑定到 this将首先创建它的临时副本,然后绑定到它。所以原来的 this 指针实际上不会受到影响。 - Joseph Mansfield
@sftrabbit:是的!与...一样: int&& x = 0;。 - GManNickG
@GmanNickG是的,我刚试过 int&& x = 5; x++; 一时间以为我改变了数学本身。现在我们将学习用1,2,3,4,6,6,7,...... - Joseph Mansfield


我说clang是对的 - 代码应该编译。由于某种原因,海湾合作委员会考虑了 this 指针是 const 尽管如下:

的类型 this 在类的成员函数中 X 是 X*。如果声明了成员函数 const,这种类型 const X*,如果声明了成员函数 volatile,这种类型 volatile X*,如果声明了成员函数 const volatile,这种类型 const volatile X*

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

对“cv1”类型的引用 T1“由”cv2“类型的表达式初始化 T2“ 如下:

  • [...]

  • [...] 要么 引用应为右值引用

    • 如果是初始化表达式

      • 是一个xvalue,类prvalue,数组prvalue或函数左值和[...],或

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

      然后 [...]

    • 除此以外,使用非参考拷贝初始化(8.5)的规则,从初始化表达式创建并初始化类型为“cv1 T1”的临时类型。然后将引用绑定到临时。 [...]


6
2018-03-21 21:43



也许是因为你在构造函数中? - Kerrek SB
@KerrekSB我没有看到这样的规则,但是,为什么会这样做 指针  const? - Joseph Mansfield
@ArmenTsirunyan那不是真的。类型的prvalue B* const 不会绑定到 B*&&,而类型的prvalue B* 将。 - Joseph Mansfield
@ArmenTsirunyan嗯,这是rvalue引用的重点。 - Joseph Mansfield
我忘了还有3.10p4: non-class prvalues always have cv-unqualified types。这意味着一个prvalue B* 永远不可能 const。 - Jesse Good