2013-03-21 62 views
11

应该编译以下示例吗?将此指针分配给指针的右值引用

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

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

int main(){} 

LWS铿锵汇编,但用gcc我得到:

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

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

我想也指出MSVC得到它太错:

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

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

BUGS FILED

MSVC bug link

GCC bug link

+1

有关信息 - 此编译在英特尔C++编译器(13.1) – teppic 2013-03-21 23:04:13

回答

8

是的,这应该编译。

它是不正确的实现thiscv 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这样的解释。 (并且你的构造函数中的值只是临时值。)

+0

实际上是否指定我们不能修改'this'?显然我们不能当它是一个prvalue,但是如果我们将它绑定到一个右值引用并通过它进行修改呢? – 2013-03-21 21:57:00

+0

有趣,所以这意味着[所选答案这个SO问题](http://stackoverflow.com/questions/7341607/so-what-is-the-type-of-this-why-is-this-not- a-lvalue)是错误的? – 2013-03-21 22:00:57

+0

@sftrabbit:这是一个prvalue和一个内置类型的副作用。这些对象不能被视为左值(一般赋值或修改)。这不适用于用户定义的类型,因为那时我们有操作符重载以及你有什么。例如,您可以在右值上调用成员函数。 – GManNickG 2013-03-21 22:02:58

6

我说铛是正确的 - 该代码应编译。出于某种原因,GCC认为this指针是const尽管以下:

在类X的成员函数的类型的this是。如果成员函数声明为const,则其类型为const X*,如果成员函数声明为volatile,则其类型为volatile X*,并且如果成员函数声明为const volatile,则其类型为const volatile X*

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

的参考输入 “CV1 T1” 是由如下类型的表达式 “CV2 T2” 初始化:

  • [...]

  • [...]或参考文献应为参考文献

    • 如果初始化表达式

      • 是一个x值,类prvalue,阵列prvalue或功能左值和[...],或

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

      然后[...]

    • 否则,临时型“CV1 T1”的创建并使用用于非参考副本初始化(8.5)的规则初始化表达式初始化。然后参考文件被绑定到临时文件。 [...]

+0

也许是因为你在构造函数中? – 2013-03-21 21:46:54

+0

@KerrekSB我没有看到这样的规则,但仍然,为什么会使* pointer *'const'? – 2013-03-21 21:48:40

+0

嗯,从头开始...但注意'this'是一个*表达*,而不是一个变量。这是一个惊喜。 – 2013-03-21 21:49:54