我正在查看这个answer,我想知道是否使用reinterpret_cast将对象转换为第一个成员并使用结果在C ++中是安全的。
我们假设我们有一个A类,一个B类和一个B的实例b:
class A{
public:
int i;
void foo(){}
};
class B{
public:
A a;
};
B b;
问题1:使用这样的b.a是否安全:reinterpret_cast<A*>(&b)->foo()
?
注意:在一般情况下,我们假设类及其成员都是标准布局。
我对reinterpret_cast上可用参考文献的讲座告诉我,这种用法应该被授权,因为没有别名违规,但它与许多答案冲突,如this one。
问题2:使用这样的b.a是否安全:static_cast<A*>(static_cast<void*>(&b))->foo()
?
答案 0 :(得分:5)
是的,因为这里的两个课程都是standard-layout types,您可以在&b
和&b.a
之间进行转换。
reinterpret_cast<A*>(p)
被定义为与static_cast<A*>(static_cast<void*>(p))
,(5.2.10p7)相同,因此您的问题都是等效的。
对于标准布局类,struct / class的地址与其第一个非静态成员(9.2p19)的地址相同。 static_cast
到/ void*
的{{1}}将保留地址(5.2.9p13),这意味着结果有效。
如果类不是标准布局,则不能依赖此行为。
答案 1 :(得分:4)
正式回答:是的,有些情况下你可以这样做(见@interjay的回答)。
实际答案:请不要这样做。真。主要是当直线路径可用时:
b.a.foo();
换句话说,如果避免使用类型转换,则不要使用类型转换。
答案 2 :(得分:0)
如果您对C ++ 98,2003感兴趣:
Q1和Q2是相同的结构。
您的类型是POD。在实例化期间POD在开始时没有填充是存在的保证....但是在继承期间它不存在保证。所以reinterpret_cast是不安全的...... my question about POD layout
“在现实生活中”它是相当安全的,因为大多数编译器在继承期间执行内存布局,如http://phpcompiler.org/articles/virtualinheritance.html
但要注意对象基地址和 B对象基地址可能具有潜在不同值的风险。