12

下面的示例应该编译吗?

struct B;
struct A
{
  A(B*&&){}
};

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

int main(){}

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

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

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

我还想指出 MSVC 也弄错了:

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

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

提交的错误

MSVC 错误链接

GCC 错误链接

4

2 回答 2

8

是的,那应该编译。

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

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

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

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

很明显,你不能修改this(比如,this = nullptr),但也清楚 noconst对于这样的解释是必要的。(而您在构造函数中的值只是临时值。)

于 2013-03-21T21:50:38.600 回答
6

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

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

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

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

  • [...]

  • [...] 或引用应为右值引用

    • 如果初始化表达式

      • 是 xvalue、类 prvalue、数组 prvalue 或函数 lvalue 和 [...],或

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

      然后 [...]

    • 否则,将使用非引用复制初始化 (8.5) 的规则从初始化表达式创建并初始化“cv1 T1”类型的临时变量。然后将引用绑定到临时文件。[...]

于 2013-03-21T21:43:42.747 回答