将指向类的指针强制转换为指向其首成员的指针是否合法?
为什么将Container指针强制转换为Member指针是合法的?
嘿,这个问题抓得很准!你觉得这种写法“非法”是非常正常的直觉,但在C++标准里,它其实是合法且行为明确的,我给你掰扯清楚背后的规则:
核心原因:标准布局类型的内存布局规则
C++标准对「标准布局类型(standard-layout type)」的内存布局有明确规定:
- 对于一个标准布局类,如果它的第一个非静态数据成员是另一个标准布局类型的对象,那么这个成员对象的地址与整个外层类对象的地址完全相同。
先看看你的代码里的类是不是符合标准布局:
Member:没有虚函数、所有成员都是public访问权限、没有基类,完全符合标准布局要求。Container:同样没有虚函数、成员都是public、第一个成员是Member类型的fooObject,也属于标准布局类型。
所以Container对象的起始地址,和它内部fooObject的起始地址是完全重合的。这时候你把Container*强制转换成Member*,本质上就是拿到了第一个成员的地址,这种转换是标准允许的,访问转换后的指针的成员(比如meb->a),其实就是访问fooObject的对应成员,所以你的测试会得到正确结果。
但请注意:这种写法极度不推荐
虽然它现在能跑通,但完全依赖于Container的成员顺序——如果哪天有人在fooObject前面加了个成员(比如int x;),这个强制转换立刻就会变成未定义行为,程序可能崩溃、输出乱码,或者出现其他诡异问题。
更安全的写法应该是直接获取成员的地址:
auto meb = &ctain->fooObject;
或者修改getMemb()让它返回引用(而不是拷贝):
Member& getMemb(){return fooObject;} // 调用时 auto& meb = ctain->getMemb();
这样既清晰又安全,完全不需要依赖内存布局的细节。
内容的提问来源于stack exchange,提问作者maidamai
相关产品推荐
相关产品推荐

