reinterpret_cast从对象到第一个成员

时间:2015-06-03 10:29:17

标签: c++ c++11 type-conversion undefined-behavior reinterpret-cast

我正在查看这个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()

3 个答案:

答案 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对象基地址可能具有潜在不同值的风险。