Размер класса с указателем this - PullRequest
7 голосов
/ 18 марта 2010

Размер класса без элементов данных возвращается как 1 байт, даже если объявлен неявный указатель this. Разве возвращаемый размер не должен быть 4 байта (на 32-битной машине)? Я наткнулся на статьи, в которых указано, что указатель «this» не учитывается при расчете размера объекта. Но я не могу понять причину этого. Кроме того, если какая-либо функция-член объявлена ​​виртуальной, размер класса теперь возвращается как 4 байта. Это означает, что vptr рассчитывается для расчета размера объекта. Почему vptr считается и указатель this игнорируется для расчета размера объекта?

Ответы [ 4 ]

6 голосов
/ 18 марта 2010

Указатель this не является членом класса. Это просто конструкция, которая используется в методах, принадлежащих классу, для ссылки на текущий экземпляр.

Если у вас есть такой класс:

class IntPair
{
public:
  IntPair(int a, int b) : _a(a), _b(b) { }

  int sum() const { return _a + _b; }

public:
  int _a;
  int _b;
};

Этому классу требуется место только для двух экземпляров int для каждого экземпляра. После создания экземпляра и запуска метода sum() этот метод вызывается с указателем на экземпляр, но этот указатель всегда приходит откуда-то еще, он не сохраняется в экземпляре объекта.

Например:

IntPair *fib12 = new IntPair(89, 144);

cout << fib12->sum();

Обратите внимание, как переменная, которая становится указателем this, сохраняется вне объекта, в области его создания.

На самом деле вы всегда можете преобразовать метод, подобный приведенному выше, в:

static int sum2(const IntPair* instance)
{
  return instance->_a + instance->_b;
}

Если вышеприведенное определено внутри класса (чтобы он мог получить доступ к закрытым членам), разницы нет. Фактически, это - это как методы реализованы за сценой; указатель this - это просто скрытый аргумент для всех методов-членов.

Звонок станет:

IntPair* fib12 = new IntPair(89, 144);

cout << IntPair::sum2(fib12);
4 голосов
/ 18 марта 2010

'this' не сохраняется как член данных в классе, это просто "указатель" на экземпляр класса. Рассматривайте это как «скрытый аргумент», передаваемый методу. На самом деле, в системах Win32 это часто передается в регистр ecx (не eax, как я думал изначально).

Как только у вас есть 1 или более виртуальных методов, вашему приложению требуется способ хранения указателей на виртуальные методы. Это называется vtable, который идентичен для всех экземпляров одного и того же класса. Поскольку во время выполнения вам необходимо знать, какой «явный» метод вызывать, для какого «виртуального метода» указатель на виртуальную таблицу хранится в экземпляре класса. Поэтому указателю vtable (или vptr) необходимо 4 байта (или 8 байтов в 64-битной системе).

2 голосов
/ 18 марта 2010

Указатель this не хранится внутри объекта. Там нет необходимости делать это. У вас уже есть указатель или объект для вызова функций. Что касается размера 1, стандарт C ++ требует, чтобы окружающие объекты имели разные адреса.

0 голосов
/ 30 апреля 2012

Размер указателя всегда равен размеру указателя, который требуется сохранить в памяти.

Например, если адрес памяти int 32-битный в 64-битной архитектуре, то

int a = 10; int * b = & a; sizeof (б); // 32 sizeof (& b); 64

...