Подтвердить что ты не робот

Методы класса увеличивают размер экземпляров класса?

Вопрос довольно прямолинейный. Для ясности рассмотрим приведенный ниже пример:

// Note that none of the class have any data members
// Or if they do have data members, they're of equal size, type, and quantity
class Foo {
public:
    void foo1();
    void foo2();
    // 96 other methods ...
    void foo99();
};

class Bar {
public:
    // Only one method
    void bar();
};

class Derived1 : public Foo { };
class Derived2 : public Bar { };

int main() {
    Foo f;
    Bar b;
    Derived1 d1;
    Derived2 d2;
    return 0;
}

У экземпляров f, b, d1 и d2 все занимают одинаковое пространство в памяти? В качестве продолжения этого вопроса копирование экземпляров Foo при его передаче займет больше времени Bar, теоретически?

4b9b3361

Ответ 1

Только данные экземпляра увеличивают размер экземпляров класса (во всех реализациях, о которых я знаю), за исключением того, что если вы добавляете виртуальные функции или наследуете от класса с виртуальными функциями, то вы принимаете одноразовый удар для v -table указатель.

Кроме того, поскольку кто-то правильно упоминает, что минимальный размер класса составляет 1 байт.

Некоторые примеры:

// size 1 byte (at least)
class cls1
{
};

// size 1 byte (at least)
class cls2
{
    // no hit to the instance size, the function address is used directly by calling code.
    int instanceFunc();
};

// sizeof(void*) (at least, for the v-table)
class cls3
{
    // These functions are indirectly called via the v-table, a pointer to which must be stored in each instance.
    virtual int vFunc1();
    // ...
    virtual int vFunc99();
};

// sizeof(int) (minimum, but typical)
class cls4
{
    int data;
};

// sizeof(void*) for the v-table (typical) since the base class has virtual members.
class cls5 : public cls3
{
};

Реализации компилятора могут обрабатывать несколько виртуальных наследований с помощью нескольких указателей v-table или других других методов, поэтому они также будут влиять на размер класса.

Наконец, параметры выравнивания данных членов могут иметь влияние. У компилятора может быть некоторая опция или #pragma, чтобы указать, что данные элемента должны иметь начальный адрес, который кратен количеству указанных байтов. Например, с выравниванием на 4 байтовых границах и предполагая sizeof(int) = 4:

// 12 bytes since the offset of c must be at least 4 bytes from the offset of b. (assuming sizeof(int) = 4, sizeof(bool) = 1)
class cls6
{
    int a;
    bool b;
    int c;
};

Ответ 2

Строго говоря, это зависит от реализации. Но количество методов не должно изменять размер объектов класса. Для не виртуальных методов внутри памяти объекта нет ничего, что связано с указателями методов. Если у вас есть виртуальные методы, каждый объект имеет один указатель на vtable. Vtable растет, когда вы добавляете больше методов, но размер указателя остается прежним.

Дополнительная информация: для не виртуальных методов компилятор отслеживает указатели методов для каждого класса. когда вы вызываете не виртуальный метод, компилятор передает указатель на метод, указывающий на объект, либо как скрытый параметр, либо в стеке. Так метод "знает" свой объект и имеет доступ к указателю this. Для виртуальных методов указатель метода фактически является индексом в таблице vtable, поэтому компилятор передает this в разыменованную запись в таблице vtable.

Ответ 3

Да, они будут. Фактически в вашем случае размер будет равен 1. В С++ класс, даже без какого-либо элемента данных, будет иметь размер 1.

Ответ 4

Foo и Bar должны быть по одному байту. Derived1 и Derived2 могут быть один или два байта.

Причина заключается в том, что компилятор хранит всю статическую информацию в исполняемом коде, включая все функции-члены. Если ваш код вызывает foo1 в экземпляре Foo, он просто вызывает Foo::foo1(this), что одинаково для каждого Foo в программе. виртуальные функции являются исключением, но не добавляют дополнительный размер для каждой функции-члена, а только одноразовый дополнительный размер (обычно 4/8 байта), если есть какие-либо виртуальные функции вообще.