Где находится указатель "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 хранящиеся в памяти?

463   6  

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

    Ничего не найдено.