How does the compiler determine the location of a member when accessing through a base pointer
This just jumped into my head and I can't figure it out.
If I have a code like this:
struct A { char x[100]; };
struct B { int data; };
struct C : A, B {};
#include <iostream>
using namespace std;
B* get_me_some_stuff()
{
static int x = 0;
if (++x % 2 == 0)
return new B();
else
开发者_如何学JAVA return new C();
}
int main()
{
B* x = get_me_some_stuff();
B* y = get_me_some_stuff();
x->data = 10;
y->data = 20;
cout << x->data << " " << y->data << endl;
return 0;
}
How does the compiler determine the memory location of the data
member?
Your x and y pointers actually point to the B subobject of the B and C objects (using the most-derived type).
Example:
int main() {
C c;
B *pb = &c; // converting the pointer here actually adjusts the address
void *pvc = &c; // doesn't adjust, merely type conversion
void *pvb = pb; // doesn't adjust, merely type conversion
cout << boolalpha;
cout << (pvc == pvb) << '\n'; // prints false
cout << (&c == pb) << '\n'; // prints true!
// (&c is converted to a B* for the comparison)
C *pc = static_cast<C*>(pb); // this static_cast, which is UB if pb doesn't
// actually point to a C object, also adjusts the address
cout << (pc == &c) << '\n'; // prints true
return 0;
}
The moral of this story? Use static_cast from void* (not reinterpret_cast), and you can only convert from void to the exact same type that was originally used to convert to void:
reinterpret_cast<C*>(pvb) // undefined behavior
Try this:
C* x = new C();
B* y = x;
cout << x << " " << y << endl;
Output for me:
0x1ae2010 0x1ae2074
The act of casting from C*
to B*
(or in the other direction) includes the necessary pointer arithmetic.
精彩评论