где помещается этот указатель и когда для него выделяется память?


Почему указатель на таблицу виртуальных функций влияет на размер класса, но этот указатель не влияет на размер класса ? где помещен этот указатель и когда для этого выделяется память?

5 2

5 ответов:

Он передается как неявный параметр и поэтому не хранится внутри объекта. Когда вы пишете:

struct X
{
    void f( int i );
};

X x;
x.f( 42 );

Вы можете думать об этом так:

void f( X* const this, int i ); // of course this would be illegal as "this" is a keyword

f( &x, 42 );

Таким образом, this-указатель исходит из того места, где вызывается метод.

Указатель на таблицу виртуальных функций хранится в объекте, но this на самом деле является скрытымпараметром функций-членов. В действительности, когда у вас есть это:

class X
{
  void foo(int bar) const;
};

int main()
{
  X x;
  x.foo(7);
}

Тогда компилятор неявно преобразует его в нечто подобное (псевдокод):

class X
{
  static void foo(const X * const this, int bar);
};

int main()
{
  X x;
  X::foo(&x, 7);
}
Обратите внимание, что я показываю псевдокод только для иллюстрации. Вы можете концептуально представить себе это так, но это не то, что происходит на самом деле.

Как и указатель' this', vptr зависит от экземпляра, а не от класса.

this указатель неявно помещается в стек (это как аргумент метода). Поэтому, когда вы вызываете obj->foo(), вы неявно передаете obj в метод foo. Компилятор предоставляет вам доступ к этому аргументу через this.

В общем случае не может быть необходимости хранить этот указатель внутри объекта в любом случае. Это было бы излишним (то есть, если бы вы могли получить доступ к объекту, его адрес уже доступен вам).

Однако VTable - это совсем другая история. Какой vtable объект указывает на то, что не может быть известно во время компиляции,и нет отдельного неявного аргумента. Для этого требуется специальное пространство в самом объекте.

Нигде. Указатель this не является значением lvalue и не занимает память как таковая. Это все равно что спрашивать, где результаты x + y пребывают (где x и y являются int). В зависимости от реализация, где он действительно будет находиться будет варьироваться: VC++, для например, стремится сохранить его в реестре ECX (хотя это может варьировать при использовании оптимизации); Sun CC for Sparc помещает его в регистр i0 и др. Это не член, даже неявный, класс. Наверное, так будет лучше. думается, как аргумент в пользу функция, хотя многие компиляторы будут относиться к ней по-особому, и в отличие от обычных аргументов, это не lvalue.