Где указатель «this» хранится в памяти компьютера?

Где именно хранится указатель «this» в памяти? Распределяется ли он в стеке, в куче или в сегменте данных?

#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 хранится в памяти?

63

Решение

Другие ответы сделали очень хорошую работу, объяснив, как реализует типичный компилятор this (передавая его как неявный первый параметр функции).

Я думаю, что также полезно посмотреть, что спецификация C ++ ISO явно говорит об этом. Согласно спецификации C ++ 03 ISO, § 9.3.2 / 1:

В теле нестатической (9.3) функции-члена ключевое слово this является выражением без значения, значение которого является адресом объекта, для которого вызывается функция.

Важно отметить, что this является не переменная — это выражение, так же, как выражение 1 + 2 * 3 это выражение. Значение этого выражения разрешено хранить практически везде. Компилятор может быть положить его в стек и передать как неявный параметр функции, или может быть поместите это в регистр, и это возможно могло бы поместить это в кучу или в сегмент данных. Спецификация C ++ намеренно дает реализации некоторую гибкость здесь.

Я думаю, что ответ «язык-юрист» — «это полностью определяется реализацией, и, более того, this технически это не указатель, а выражение, которое оценивает указатель «.

Надеюсь это поможет!

63

Другие решения

Самый простой способ — подумать 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);

Обратите внимание, что приведенное выше преобразование упрощено, и, надеюсь, немного прояснит мою точку зрения. Нет необходимости заполнять комментарии словами: «аааа, а где маршаллинг для перегрузки методов?» — напишите возражение, пожалуйста. 🙂

Это превращает вопрос в «где хранятся аргументы?», И ответ, конечно, «это зависит». 🙂

Он часто находится в стеке, но может быть и в регистрах, или любой другой механизм, который компилятор считает подходящим для целевой архитектуры.

78

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 рассматривается как обычный параметр этого метода.

33

this является значением (вы не можете взять его адрес), поэтому он не
(обязательно) занимают память вообще. В зависимости от компилятора
и целевая архитектура, это часто будет в регистре: i0
на Sparc, ECX с MSVC на Intel и т. д. Когда оптимизатор
активный, он может даже двигаться. (Я видел это в разных
регистрируется в MSVC).

18

this ведет себя в основном как аргумент функции и как таковой будет храниться в стеке или — если двоичные соглашения о вызовах архитектуры допускают это — в регистре.

9

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
}

В цепочке активации функции также будет несколько копий указателя this. Предположим, у нас есть объект obj и назовите его foo функция. Эта функция вызывает тот же объект bar функция и bar вызывает другую функцию под названием update, Каждый уровень активации функции имеет this указатель. Он хранится в регистре машины или в ячейке памяти в стековом кадре активации функции.

0
По вопросам рекламы [email protected]