凡被存储在计算机内存中的“这个”指针?(Where is the 'this' po

2019-09-03 16:05发布

到底在哪存储在内存中的“这个”指针? 难道是在栈上分配的,在堆上,或在数据段?

#include <iostream>
using namespace std;

class ClassA
{
    int a, b;

    public:
        void add()
        {
            a = 10;
            b = 20;
            cout << a << b << endl;
        }
};

int main()
{
    ClassA obj;
    obj.add();
    return 0;
}

在上面的代码我打电话成员函数add()和接收器对象是隐式传递作为“本”的指针。 哪里是this存储在内存中?

Answer 1:

其他答案都做了很好的工作说明普通的编译器如何实现this (通过将其作为一个隐含的第一个参数的函数)。

我认为这也非常有用,看看C ++ ISO规范明确地说这件事。 根据C ++ 03 ISO规格,§9.3.2/ 1:

在一个非静态(9.3)成员函数的主体,关键字this是一个非左值表达式,其值是用于该函数被调用的对象的地址。

需要注意的是很重要的this不是一个变量-这是一个表达 ,多以同样的方式,表达1 + 2 * 3是一个表达式。 这个表达式的值被允许几乎任何地方保存。 编译器可能把它的堆栈上,并将其传递作为隐式参数的功能,或者它可能把它放在一个寄存器中,并且它可以想到可以把它在堆或在数据段。 在C ++规范特意在这里给执行一定的灵活性。

我认为,“语言律师”的回答是:“这是完全实现定义,而且this在技术上是一个指针,但计算结果为指针的表现。”

希望这可以帮助!



Answer 2:

最简单的方法是想this作为一个始终自动传递一个隐藏的额外的参数。

因此,一个虚构的方法,如:

size_t String::length(void) const
{
  return strlen(m_string);
}

其实更像是这样的引擎盖下:

size_t String__length(const String *this)
{
  return strlen(this->m_string);
}

和调用,比如:

{
  String example("hello");
  cout << example.length();
}

成为类似:

cout << String__length(&example);

需要注意的是,上述转变被简化,希望能够使我的观点更清楚一点。 无需填补评论与“whaaa,哪来的方法重载编组,是吧?” - 类型的异议,请。 :)

这个转变的问题为“存储在哪里有观点?”,答案当然是“看情况”。 :)

它往往是在栈中,但它可能是在寄存器中太,或编译器认为任何其他机制是良好的目标架构。



Answer 3:

this通常是因为该方法的一个隐藏的参数传递(在整个不同的调用约定,唯一的区别是如何 )。

如果您致电:

myClass.Method(1, 2, 3);

编译器生成以下代码:

Method(&myClass, 1, 2, 3);

当第一个参数实际上是指向this

让我们来看看下面的代码:

class MyClass
{
private:
    int a;

public:
    void __stdcall Method(int i)
    {
        a = i;
    }
};

int main(int argc, char *argv[]) 
{
    MyClass myClass;
    myClass.Method(5);

    return 0;
}

通过使用__stdcall我强迫编译器通过堆栈传递的所有参数。 如果然后启动调试和检查汇编代码,你会发现类似如下:

     myClass.Method(5);
00AA31BE  push        5  
00AA31C0  lea         eax,[myClass]  
00AA31C3  push        eax  
00AA31C4  call        MyClass::Method (0AA1447h)  

正如你看到的,该方法的参数通过堆栈传递,然后MyClass的地址加载到EAX寄存器,并再次压入堆栈。 换句话说, this将被视为该方法的常规参数。



Answer 4:

this是一个右值(你不能把它的地址),所以它不(一定)占用内存的。 根据不同的编译器和目标体系结构,它往往会在寄存器中:在SPARC,ECX与MSVC英特尔,I0等当优化是积极的,它甚至可以左右移动。 (我用MSVC看到它在不同的寄存器)。



Answer 5:

this行为大多喜欢函数参数,因此将被存储在栈上或-如果该体系结构的二进制调用约定允许-在寄存器中。



Answer 6:

this不是存储在一个定义良好的位置! 它指向的对象是存储的地方,并有一个明确的地址,但该地址本身并没有一个具体的家庭住址。 它在节目传达左右。 不仅如此,但也有可能是指针的许多副本。

在以下的假想init功能,对象自身注册以接收事件和定时器回调(使用假想事件源对象)。 因此,在注册后,还有两个额外的副本this

void foo_listener::init()
{
   g_usb_events.register(this); // register to receive USB events
   g_timer.register(this, 5);   // register for a 5 second timer
}

我一个功能激活链,也将是这个指针的多个副本。 假设我们有一个对象obj并调用foo功能。 该函数调用同一个对象的bar功能,以及bar调用另一个叫功能update 。 每个函数激活水平有this指针。 它存储在机器寄存器,或者在功能激活的堆栈帧的存储器位置。



文章来源: Where is the 'this' pointer stored in computer memory?