'this' 中使用的关键字 class and objects 是一个常量指针?

'this' keyword used in class and objects is a constant pointer?

由于我的 c++ 程序中出现以下错误,我想到了这个问题

#include <iostream>
using namespace std;
class Test
{
private:
  int x;
public:
  Test(int x = 0) { this->x = x; }
  void change(Test *t) { this = t; }
  void print() { cout << "x = " << x << endl; }
};

int main()
{
  Test obj(15);
  Test *ptr = new Test (100);
  obj.change(ptr);
  obj.print();
  return 0;
}

错误:

main.cpp:18:31: error: lvalue required as left operand of assignment
   18 | void change(Test *t) { this = t; }
      |    

我搜索了一下这个错误,发现它通常发生在我们尝试将赋值运算符左侧的常量赋值给右侧的变量时。如有不妥请指正

谢谢

From cppreference this:

The keyword this is a prvalue expression whose value is the address of the implicit object parameter (object on which the non-static member function is being called).

您不能分配给 rvalues(例如 1 = obj 无效)。因此,您必须取消引用 this 并分配。

*this = *t;

回答题目,

this keyword used in class and objects is a constant pointer?

不,不是。即使一个成员函数被标记为 const 那么它仍然是一个指向 const 对象的指针。

来自 cppereference,

The type of this in a member function of class X is X* (pointer to X). If the member function is cv-qualified, the type of this is cv X* (pointer to identically cv-qualified X).

根据9.3.2 The this pointer [class.this]

1 In the body of a non-static (9.3) member function, the keyword this is a prvalue expression whose value is the address of the object for which the function is called. [...]

所以正如错误所说,左侧 应该是 一个 lvalue 但你给它一个 prvalue 因为 change 是一个非静态成员函数并且在任何非静态成员函数中关键字 this 是一个 prvalue 根据上面引用的声明。因此错误。

但是可以修改this指向的对象,如下图:

#include <iostream>
using namespace std;
class Test
{
private:
  int x;
public:
  Test(int x = 0) { this->x = x; }
  void change(Test *t) { *this = *t; }//THIS WORKS 
  void print() { cout << "x = " << x << endl; }
};

int main()
{
  Test obj(15);
  Test *ptr = new Test (100);
  obj.change(ptr);
  obj.print();
  return 0;
}

请注意,在上面的示例中,我已将 this = t; 替换为

*this = *t;//this time it works because now the left hand side is an lvalue 

这次程序可以运行了,因为现在左边是一个左值

更多解释

来自 IBM's this pointer documentation,

this 参数具有 类型 Test *const。也就是说,它是一个指向Test对象的常量指针。现在因为它是常量指针,你不能使用 this = t; 给它分配一个不同的指针值。因此错误。

同样,来自Microsoft's this pointer documentation

the this pointer is always a const pointer. It can't be reassigned.

所以这也解释了您遇到的错误。

在非const成员函数中,this的类型是"Type* const this",而在const成员函数中是"const Type* const this"。所以你不能改变一个 const this 值来让它指向另一个地址。你可以使用下面的代码来模拟它:

struct A{
    int a;
};
int main() {
      A* const p = new A();
      p = new A();    
      return 0;
}

你会得到同样的错误

下图显示了const成员函数和非常量成员函数中this的类型: