c++object-model

How does the compiler distinguish nested objects if they have the same address?


In the following example (try out here)

#include <iostream>
using namespace std;

struct a {
    struct b {
        int b1;
    };
    b a1;
    int a2;
};
int main() {
    a test;
    test.a1.b1 = 5;
    test.a2 = 6;

    std::cout<<&test<<" "<<&(test.a1);
    // your code goes here
    return 0;
}

Both the struct and its nestd struct have the same memory location. This makes sense, since the first element to be stored in memory is part of the nested struct.

Proof: 0x7ffd895f86e0 0x7ffd895f86e0

My question is: how does the compiler know what types are stored at this location and is there any overhead from tracking such information at runtime to be expected?


Solution

  • How about this:

    struct a {
        int x;
        struct b {
            int b1;
        };
        b a1;
        int a2;
    };
    

    Do they have the same address? No. Not because they're different, but because "struct" has no binary meaning (before lashing this, keep reading). When your program is compiled, all that matters is the variables inside your structs. The programming language has this superficial thing called "struct" to make things easy for you. But it's not real, unless you do something that requires it to be handled as a one thing (such as copying it), and even then the binary code generated (for run-time) will only represent the elements that are to be copied as a whole, not the "struct", per se.

    When you instantiate a there, this is how it looks like in memory:

    int x - int b1 - int a2
    

    It's blocks in memory with ints. It's not structs.

    You can verify this using pointers. In your code:

    *(int*)(&test) //is b1
    *((int*)(&test)+1) //is a2
    

    So you see there's only two ints in memory that matter.

    PS: Notice that all this assumes that we're not dealing with polymorphism, which adds more memory blocks that represent the vtable. That's a story for another day.