Где находится указатель "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() и объект receiver передается неявно как указатель 'this'. Где же this хранящиеся в памяти?
6 ответов:
другие ответы сделали очень хорошую работу, объясняя, как типичный компилятор реализует
this(передавая его в качестве неявного первого параметра функции).Я думаю, что также полезно посмотреть, что спецификация c++ ISO явно говорит об этом. Согласно спецификации ISO C++03, §9.3.2 / 1:
в теле нестатической (9.3) функции-члена ключевое слово
this- Это выражение без значения lvalue, значение которого является адресом объекта, для которого вызывается функция.важно отметить, что
thisи не переменная - это выражение, почти так же, как выражение1 + 2 * 3- Это выражение. Значение этого выражения можно хранить практически в любом месте. Компилятор может поместите его в стек и передайте его как неявный параметр функции, или это может положите его в регистр, и он предположительно может поставить это в куче или в сегменте данных. Спецификация C++ намеренно дает реализации некоторую гибкость здесь.Я думаю, что ответ "язык-юрист": "это полностью определено реализацией, и более того
thisтехнически не указатель, а выражение, которое вычисляет указатель."надеюсь, что это помогает!
самый простой способ-думать о
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, где сортировка для перегрузки метода, а?"типа возражений, пожалуйста. :)
что превращает вопрос В "где хранятся аргументы?"и ответ, Конечно, "это зависит". :)
он часто находится в стеке, но он также может быть в регистрах или любом другом механизме, который компилятор считает хорошим для целевой архитектуры.
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обрабатывается как обычный параметр этого метода.
thisявляется rvalue (вы не можете взять его адрес), так что это не так (обязательно) занимайте память вообще. В зависимости от компилятора и целевая архитектура, она часто будет в регистре: i0 на Sparc, ECX с MSVC на Intel и др. Когда оптимизатор является активный, он может даже передвигаться. (Я видел это по-разному регистры с MSVC).
thisведет себя в основном как аргумент функции, и как таковой будет храниться в стеке или - если бинарные соглашения о вызовах архитектуры позволяют это - в регистре.
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 }I цепочка активации функции, также будет несколько копий этого указателя. Предположим у нас есть объект
objи назвать его
Comments