Структура данных класса

Какова структура данных класса C ++?
как это работает на уровне сборки?

Оператор IF — это сравнение + условный переход строки кода.

Массив и строка — это цепное звено данных.

-6

Решение

Компилятор назначает смещения для всех элементов и включает их во все операции загрузки / сохранения элементов:

struct foo {
uint32_t bar;
uint32_t baz;

uint32_t get_baz() { return baz; }
};

uint32_t get_baz_from_foo(foo *f) { return f->baz; }

становится (код ассемблера ARM используется для простоты):

foo__get_baz:
; calling convention: this pointer in r3
; load 32 bit value from r3 + 4 bytes into r0
ldr r0, [r3, #4];
; calling convention: return value in r0
; return from subroutine
b lr

get_baz_from_foo:
; calling convention: first parameter in r0
; load 32 bit value from r0 + 4 bytes into r0
ldr r0, [r0, #4]
; calling convention: return value in r0
; return from subroutine
b lr

Как struct соответственный class макет не изменяется после компиляции, здесь 4 жестко закодирован в поток команд.

Создание экземпляра работает путем выделения памяти и передачи указателя из функции выделения всем, кто ожидает указатель на структуру:

new__foo:
; two 32 bit integers need 8 bytes
; calling convention: first parameter in r0
mov r0, #8
; call allocator, which will then return to the function invoking new
bra malloc

Если есть конструктор

struct foo2 {
foo2() : bar(5), baz(7) { }
uint32_t bar;
uint32_t baz;
uint32_t get_baz() { return baz; }
};

В итоге мы получим немного более сложный способ создания объектов (который вы сможете понять без комментариев):

new__foo2:
strdb lr, ![sp]
mov r0, #8
bl malloc
mov r1, #5
str r1, [r0]
mov r1, #7
str r1, [r0, #4]
ldaia lr, ![sp]
b lr

get_baz реализация такая же, как для foo учебный класс.

Теперь, если я создам такой объект и получу значение baz:

    bl new__foo2
; remember: the this pointer goes to r3
mov r3, r0
bl foo2__get_baz

Я заканчиваю с r0 содержащий значение 7,

За virtual методы, создается скрытый элемент данных, который является указателем на таблицу функций:

struct base {
virtual uint32_t get_baz() = 0;
};

struct derived : base {
derived() : baz(5) { }
virtual uint32_t get_baz();
uint32_t bar;
uint32_t baz;
};

становится

new__derived:
strdb lr, ![sp]
mov r0, #12
bl malloc
mov r1, #5
str r1, [r0, #8]
; get the address of the vtable
ldr r1, =vtable__derived
; vtable typically goes to the end of the class defining it
; as this is the base class, it goes before derived's data members
str r1, [r0]
ldria lr, ![sp]
b lr

vtable__derived:
; pointer to function
dw derived__get_baz

derived__get_baz:
ldr r0, [r3, #8]
b lr

Вызов этой функции выполняется косвенно:

    ; construct normally
bl new__derived
; here, we forget that this is a "derived" object
; this pointer to r3
mov r3, r0
; get vtable ptr
ldr r0, [r3]
; get function ptr from vtable
ldr r0, [r0]
; call function
bl r0

Вот, r0 сейчас 5потому что это то, что конструктор хранит там.

3

Другие решения

Других решений пока нет …