首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >'this‘指针存储在计算机内存中的什么地方?

'this‘指针存储在计算机内存中的什么地方?
EN

Stack Overflow用户
提问于 2013-05-16 18:54:55
回答 6查看 11.1K关注 0票数 65

“this”指针存储在内存中的确切位置?它是在堆栈上、堆中还是数据段中分配的?

代码语言:javascript
复制
#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‘指针传递。this在内存中存储在哪里?

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2013-05-16 23:54:44

其他答案很好地解释了典型的编译器如何实现this (通过将其作为隐式的第一个参数传递给函数)。

我认为看看C++ ISO规范明确说明了这一点也很有用。根据C++03 ISO规范,§9.3.2/1:

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

需要注意的是,this is 不是一个变量-它是一个表达式,就像表达式1 + 2 * 3是一个表达式一样。这个表达式的值被允许存储在几乎任何地方。编译器可能会将它放到堆栈中,并将其作为隐式参数传递给函数,或者它可能会将它放在寄存器中,并且可以想象它会将它放入堆或数据段中。在这里,C++规范有意地为实现提供了一些灵活性。

我认为“语言律师”的答案是“这是完全由实现定义的,而且从技术上讲,this不是一个指针,而是一个计算结果为指针的表达式。”

希望这能有所帮助!

票数 65
EN

Stack Overflow用户

发布于 2013-05-16 18:56:57

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

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

代码语言:javascript
复制
size_t String::length(void) const
{
  return strlen(m_string);
}

实际上更像是这样的:

代码语言:javascript
复制
size_t String__length(const String *this)
{
  return strlen(this->m_string);
}

和一个类似这样的调用:

代码语言:javascript
复制
{
  String example("hello");
  cout << example.length();
}

变得类似于:

代码语言:javascript
复制
cout << String__length(&example);

请注意,上面的转换被简化了,希望能让我的观点更清晰一点。不需要在注释中填上“哇,方法重载的编组在哪里?”-type反对。:)

这就将问题转化为“参数存储在哪里?”,答案当然是“视情况而定”。:)

它通常在堆栈上,但也可以在寄存器中,或者编译器认为对目标体系结构有利的任何其他机制中。

票数 79
EN

Stack Overflow用户

发布于 2013-05-16 18:59:58

this通常作为方法的隐藏参数传递(不同调用约定中唯一的区别是如何传递)。

如果你打电话给:

代码语言:javascript
复制
myClass.Method(1, 2, 3);

编译器生成以下代码:

代码语言:javascript
复制
Method(&myClass, 1, 2, 3);

其中第一个参数实际上是指向this的指针。

让我们检查一下以下代码:

代码语言:javascript
复制
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,我强制编译器通过堆栈传递所有参数。如果您随后启动调试器并检查汇编代码,您将发现类似以下内容:

代码语言:javascript
复制
     myClass.Method(5);
00AA31BE  push        5  
00AA31C0  lea         eax,[myClass]  
00AA31C3  push        eax  
00AA31C4  call        MyClass::Method (0AA1447h)  

如您所见,该方法的参数通过堆栈传递,然后将myClass的地址加载到eax寄存器并再次推送到堆栈上。换句话说,this被视为此方法的常规参数。

票数 35
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16585562

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档