如果`this`不是const,为什么我不能修改它?

25

在C++标准中,关于The this pointer [class.this]的规定如下:

在类X的成员函数中,this的类型为X*

也就是说,this指针不是const。但为什么会这样呢?

struct M {
    M() { this = new M; }
};

提供

error: invalid lvalue in assignment  <-- gcc
'=' : left operand must be l-value   <-- VC++
'=' : left operand must be l-value   <-- clang++
'=' : left operand must be l-value   <-- ICC
(source: some online compiler frontends)

换句话说,this 不是 const,但它确实是!


7
关键字 this 不是一个变量,因此我们不能声明它是常量还是非常量。 - fatihk
即使这样可以工作,那么你只是构建了一个无限循环。 - vlad_tepesch
@vlad_tepesch:要么是那样,要么是无限递归(就像你可以在Python中做的那样)。不过这不是问题所在。 - Sebastian Mach
1个回答

45

因为在同一段落中,还提到了this是一个prvalue(“纯右值”)。

标准中提到纯右值的例子包括调用不返回引用的函数的结果,或者像 1true 或者 3.5f 这样的字面值。指针 this 并不是一个变量,更像是扩展为“调用该函数的对象的地址”的字面值([class.this])。就像字面量true的类型是bool而不是bool const一样,this的类型是X*而不是X*const


3
在C++中,值具有类型值类别this的类型是X*,其值类别是prvalue。为什么会觉得这不直观呢?this必须是一个prvalue(&this没有意义) - 既然它已经是不可修改的,为什么要将其类型设为X* const呢? - Angew is no longer proud of SO
3
需要补充的是,有些语言中,“this”(或其等效物)是可修改的。例如,在Python中,“class X: def init(self): self = X() s = X()”会导致“maximum recursion depth exceeded”而不是编译错误。 - Sebastian Mach
非常清晰简洁,点赞。我现在更明白C++了 :)(主要是对纯右值的解释)。 - Sellorio
5
@busy_wait说:不是规范指定的,但例如MSVC++使用ECX寄存器。你不能取寄存器的地址。 - MSalters
1
@busy_wait:正如phresnel所说,有些语言允许您修改this指针。例如Objective-C。它也非常善于利用这一点,因为这种自由(以及其他一些自由)使得抽象基类可以在初始化时默默地提供其子类的实例,交换对象。非常适合实现隐藏。或者让构造函数返回一个已经存在的对象,确保标识和相等性的等价性等等。我自己曾经遇到过这样的情况,在C++中能够做出这样的技巧,但是不幸的是,这是不可能的... - cmaster - reinstate monica
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接