Kelbon
Kelbon

Reputation: 21

Does members of class location in memory depend on the location of class members in the class definition?

I have a part of chain class

template <typename T> 
class Part
{
public:

part* prev;
part* next;
T data;
}

Size of T is undefined now and i think it must be better to place it in the end in memory.

For example, if I move 8 bytes to the right, then I’ll definitely go to the beginning of the next class member (on a 64 bit system), and if I first put T, then I don’t know where I will go. Will I influence how the class members are located in memory or the compiler will do everything as he wants?

And can i help to perfomance with use it?

Upvotes: 0

Views: 57

Answers (1)

Francis Cugler
Francis Cugler

Reputation: 7915

I can't say for sure because it is implementation-defined between various compilers...

I added this to your code:

template <typename T>
class Part {
public:
    Part* prev;
    Part* next;
    T data;
};

template<typename T>
Part<T> makeClass(T value) {
   Part<T> part{};
   part.data = value;
   return part;
}

int main() {
    auto p = makeClass(12);
    return 0;
}

And I tested it between x86-64 clang (trunk), x86-64 gcc (trunk) and x64 msvc v19.24 on Compiler explorer found here all with the compiler settings set to -std=c++17 -O3.

If we look at the generated assembly between the three we see the following:

Clang

main:                                   # @main
        xor     eax, eax
        ret

GCC

main:
        xor     eax, eax
        ret

MSVC

part$ = 0
$T1 = 64
value$ = 72
Part<int> makeClass<int>(int) PROC       ; makeClass<int>, COMDAT
$LN3:
        mov     DWORD PTR [rsp+16], edx
        mov     QWORD PTR [rsp+8], rcx
        push    rsi
        push    rdi
        sub     rsp, 40                             ; 00000028H
        lea     rax, QWORD PTR part$[rsp]
        mov     rdi, rax
        xor     eax, eax
        mov     ecx, 24
        rep stosb
        mov     eax, DWORD PTR value$[rsp]
        mov     DWORD PTR part$[rsp+16], eax
        lea     rax, QWORD PTR part$[rsp]
        mov     rdi, QWORD PTR $T1[rsp]
        mov     rsi, rax
        mov     ecx, 24
        rep movsb
        mov     rax, QWORD PTR $T1[rsp]
        add     rsp, 40                             ; 00000028H
        pop     rdi
        pop     rsi
        ret     0
Part<int> makeClass<int>(int) ENDP       ; makeClass<int>

$T1 = 32
$T2 = 56
p$ = 80
main    PROC
$LN3:
        push    rsi
        push    rdi
        sub     rsp, 120                      ; 00000078H
        mov     edx, 12
        lea     rcx, QWORD PTR $T2[rsp]
        call    Part<int> makeClass<int>(int)      ; makeClass<int>
        lea     rcx, QWORD PTR $T1[rsp]
        mov     rdi, rcx
        mov     rsi, rax
        mov     ecx, 24
        rep movsb
        lea     rax, QWORD PTR p$[rsp]
        lea     rcx, QWORD PTR $T1[rsp]
        mov     rdi, rax
        mov     rsi, rcx
        mov     ecx, 24
        rep movsb
        xor     eax, eax
        add     rsp, 120                      ; 00000078H
        pop     rdi
        pop     rsi
        ret     0
main    ENDP

Looking at the generated assembly from various compilers might help you to determine what is happening within your code and its data alignment. After looking at those values with the optimizer at level 3, change it to level 2, 1, then 1 and see the difference in the generated assembly. This might give you some insight!

A tip from the pros - trust your compiler!

Upvotes: 1

Related Questions