где помещается этот указатель и когда для него выделяется память?
Почему указатель на таблицу виртуальных функций влияет на размер класса, но этот указатель не влияет на размер класса ? где помещен этот указатель и когда для этого выделяется память?
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
указатель неявно помещается в стек (это как аргумент метода). Поэтому, когда вы вызываетеobj->foo()
, вы неявно передаете obj в метод foo. Компилятор предоставляет вам доступ к этому аргументу черезthis
.В общем случае не может быть необходимости хранить этот указатель внутри объекта в любом случае. Это было бы излишним (то есть, если бы вы могли получить доступ к объекту, его адрес уже доступен вам).
Однако VTable - это совсем другая история. Какой vtable объект указывает на то, что не может быть известно во время компиляции,и нет отдельного неявного аргумента. Для этого требуется специальное пространство в самом объекте.
Нигде. Указатель
this
не является значением lvalue и не занимает память как таковая. Это все равно что спрашивать, где результатыx + y
пребывают (гдеx
иy
являютсяint
). В зависимости от реализация, где он действительно будет находиться будет варьироваться: VC++, для например, стремится сохранить его в реестре ECX (хотя это может варьировать при использовании оптимизации); Sun CC for Sparc помещает его в регистрi0
и др. Это не член, даже неявный, класс. Наверное, так будет лучше. думается, как аргумент в пользу функция, хотя многие компиляторы будут относиться к ней по-особому, и в отличие от обычных аргументов, это не lvalue.