Накладные расходы на создание нового класса
Если у меня есть класс, определенный как таковой:
class classWithInt
{
public:
classWithInt();
...
private:
int someInt;
...
}
и что someInt
является единственной и единственной переменной-членом в classWithInt
, насколько медленнее было бы объявлять новый экземпляр этого класса, чем просто объявить новое целое число?
Как насчет того, когда у вас есть, скажите 10 таких целых чисел в классе? 100?
Ответы
Ответ 1
С компилятором, не написанным пьяными студентами в утренние часы утра, накладные расходы равны нулю. По крайней мере, пока вы не начнете вводить функции virtual
; то вы должны оплатить стоимость виртуального механизма отправки. Или, если у вас есть нет данные в классе, и в этом случае класс по-прежнему должен занимать некоторое пространство (что, в свою очередь, связано с тем, что каждый объект должен иметь уникальный адрес в памяти).
Функции не являются частью макета данных объекта. Они являются лишь частью ментальной концепции объекта. Функция преобразуется в код, который принимает экземпляр объекта в качестве дополнительного параметра, а вызовы функции-члена соответственно переводится для передачи объекта.
Число членов данных не имеет значения. Сравните яблоки с яблоками; если у вас есть класс с 10 int в нем, тогда он занимает то же место, что и 10 ints.
Выделение вещей в стеке эффективно бесплатно, независимо от того, что они собой представляют. Компилятор добавляет размер всех локальных переменных и одновременно настраивает указатель стека, чтобы освободить место для них. Выделение пространства в памяти стоит, но стоимость, вероятно, будет больше зависеть от количества распределений, чем объем выделенного пространства.
Ответ 2
Хорошо, давайте просто протестируем все это. Я могу скомпилировать с полной оптимизацией более полный пример:
void use(int &);
class classWithInt
{
public:
classWithInt() : someInt(){}
int someInt;
};
class podWithInt
{
public:
int someInt;
};
int main() {
int foo;
classWithInt bar;
podWithInt baz;
use(foo);
use(bar.someInt);
use(baz.someInt);
return 5;
}
И это результат, который я получаю от gcc-llvm
; ModuleID = '/tmp/webcompile/_21792_0.bc'
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64-linux-gnu"
%struct.classWithInt = type { i32 }
define i32 @main() {
entry:
%foo = alloca i32, align 4 ; <i32*> [#uses=1]
%bar = alloca %struct.classWithInt, align 8 ; <%struct.classWithInt*> [#uses=1]
%baz = alloca %struct.classWithInt, align 8 ; <%struct.classWithInt*> [#uses=1]
%0 = getelementptr inbounds %struct.classWithInt* %bar, i64 0, i32 0 ; <i32*> [#uses=2]
store i32 0, i32* %0, align 8
call void @_Z3useRi(i32* %foo)
call void @_Z3useRi(i32* %0)
%1 = getelementptr inbounds %struct.classWithInt* %baz, i64 0, i32 0 ; <i32*> [#uses=1]
call void @_Z3useRi(i32* %1)
ret i32 5
}
declare void @_Z3useRi(i32*)
В каждом случае есть некоторые различия. В простейшем случае тип