this.attribute 应该是 this->attribute 是什么意思

What is the meaning of this.attribute when it should be this->attribute

我正在开发一个 C++ 程序,在调试时我正在使用以下函数:

int CClass::do_something()
{
  ... // I've put a breakpoint here
}

我的 CClass 有一个属性,我们称它为 att

当我的程序在我的断点处停止时,我在我的 Watch 中放了三样东西 window:

att
this->att
this.att

前两个 attthis->att 包含正确的值,但是 this.att 包含错误的值(至少看起来是错误的)。

它显示价值的事实意味着 this.att 具有某种意义。 那是什么意思?与 this->att 相比,this.att 的含义是什么?

供您参考,我使用 Visual Studio 作为开发环境。

箭头运算符->对左边的一个pointer进行运算,意思是访问左边的指针所指向的运算符。正如许多其他地方指出的那样, -> 运算符是 shorthand 用于手动取消引用指针并使用点表示法。 a->b == (*a).b。这意味着它需要查找的上下文信息,它可以通过指针值找到。点运算符 . 假定您有对左侧对象的引用,因此它不需要先取消引用其左侧的指针。

如果您的调试器以某种方式允许您使用点运算符而不是箭头运算符,可能是因为它没有(或不能)验证所使用的类型,它将假定指针变量的地址,而不是值指向的地址持有的地址是对象。

换句话说,它会在内存中的某个位置查看对象,而不是对象本身。该行为很可能是未定义的,您只会看到垃圾数据,即实际存储在成员 att.

的内存偏移量中的垃圾数据

假设您的对象的布局使得属性 foo 位于偏移量 0,属性 att 位于偏移量 4,那么调试器基本上是在查看对象实例加上你的成员变量持有的任何偏移量。我不在家里的电脑旁,但我可以添加一个草图,稍后再澄清。

att 本身,return 是 class.

实例的成员变量 att

this->att return 与 att 相同,只是 this-> 明确告诉程序 return att 成员class.

的变量

attthis->att 会 return 不同值的情况示例是 att 在 class 内的局部范围内重新定义.在这种情况下,att 将引用本地定义的 attthis->att 将引用 class.

att 成员变量

由于 this 是指向当前对象的指针,因此它需要 -> 表示法(它是取消引用指针和 member/method 访问的组合)。 . 符号只是 member/method 访问。要回答你 "what is the meaning of this.att" 的问题,我会说它毫无意义,老实说,我很惊讶它甚至 return 编辑了任何东西。

可以将 this. 一起使用的唯一 "right" 方法是先取消对指针的引用,如下所示:

(*this).att

但是,如果只使用 ->.

,结果是一样的,语法也是一样的

好吧,只是盲目猜测,没有进一步的信息,但让我试着理解您在调试器中看到的内容,因为这是您的问题,对吧?所以我就不解释.->的区别了。假设以下情况:

class CClass 
{ 
    int x; // at offset 0 of CClass
    int att; // at offset 4 of CClass
};

CClass* p = // ... (say p points to the address 0xF0 for now)

int CClass::do_something
{
    CClass q;
    CClass* r;
}

因此,现在在调试器中检查表达式 p->att 的值,调试器所做的是获取 p 的值(此处为 0xF0)并添加偏移量att 到它,导致内存地址 0xF4。在此地址读取 4 个字节的内存(因为我们有一个 int)并将其解释为一个带符号的整数。对于上述情况,这应该显示p指向的对象的att成员的正确值。

现在,假设您在 do_something 函数内部,其中有一个 CClass 的堆栈分配实例。如果您现在尝试获取 q.att 的值,调试器将获取对象本身的地址(基本上是 &q)并再次添加相应的偏移量 4。由于 q 分配在堆栈,&q + 4 处的内存片段是堆栈帧内存储对象 q 的成员 att 的值的位置。目前一切正常。

接下来,考虑表达式 r.att,它不是正确键入的 C++,但调试器似乎只是以通常的方式进行。它取 r (&r) 的地址,而不是 r 指向的地址,并再次向其添加 att (4) 的偏移量, 在从此位置读取 int 之前。由于r的地址在栈上,所以得到的位置&r + 4并不是r指向的对象的成员所在的位置,而是你内部的一个不相关的位置堆栈帧(就像在其他局部变量或函数参数中一样)。

在您的情况下,this 也是如此。由于 this 指针是非 static 成员函数的第一个不可见参数,因此它也位于函数的堆栈帧中。调试器现在似乎获取 this 指针在堆栈帧中的地址,添加相应的偏移量并输出在那里找到的 4 字节的值。实际值是什么,取决于堆栈帧的布局(可能类似于 return 地址),但它显然不在 this 指向的对象内。