几乎pod数据的reinterpret_cast(布局兼容性足够)

Tom*_*Tom 8 c++ static-cast reinterpret-cast

我正在努力学习static_castreinterpret_cast.

如果我是正确的,标准(9.2.18)说reinterpret_castpod数据是安全的:

指向POD结构对象的指针(适当地使用a转换) reinterpret_cast指向其初始成员(或者如果该成员是位字段,则指向它所驻留的单元),反之亦然.[注意:因此,在POD-struct对象中可能存在未命名的填充,但不是在其开头,以实现适当的对齐. - 结束说明]

我的问题是如何严格解释这一点.例如,布局兼容性足够吗?如果没有,为什么不呢?

对我来说,以下示例显示了严格的"仅POD有效"解释似乎是错误的示例.

class complex_base  // a POD-class (I believe)
{
public:  
  double m_data[2];
};

class complex : public complex_base
{  //Not a POD-class (due to constructor and inheritance)
public:
  complex(const double real, const double imag); 
}

double* d = new double[4];
//I believe the following are valid because complex_base is POD
complex_base& cb1 = reinterpret_cast<complex_base&>(d[0]);  
complex_base& cb2 = reinterpret_cast<complex_base&>(d[2]);
//Does the following complete a valid cast to complex even though complex is NOT POD?
complex& c1 = static_cast<complex&>(cb1);
complex& c2 = static_cast<complex&>(cb2);
Run Code Online (Sandbox Code Playgroud)

此外,如果complex_base::m_data受到保护可能会破坏(意味着complex_base不是吊舱)?[编辑:我如何保护自己/检测此类破损]

在我看来,布局兼容性应该足够了 - 但这似乎不是标准所说的.

编辑:谢谢你的答案.他们也帮助我找到了这个, http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2342.htm

Joh*_*itb 5

我相信以下内容是有效的,因为complex_base是POD

你错了.d[0]不引用complex_base对象的第一个成员.因此,它的对齐可能对于一个complex_base对象来说不够好,因此这样的演员表是不安全的(并且你引用的文字不允许).

即使复杂不是POD,以下是否完成了对复杂的有效转换?

cb1并且cb2不指向类型对象的子对象complex,因此static_cast产生未定义的行为.参见C++ 03的5.2.9p5

如果类型"cv1 B"的左值实际上是类型D的对象的子对象,则左值引用类型D的封闭对象.否则,未定义强制转换的结果.

仅仅涉及的类型合在一起是不够的.该文本讨论了指向POD结构对象的指针以及指向某个子对象的左值.复杂和complex_base是标准布局对象.C++ 0x规范说,而不是你引用的文字:

POD-ness要求是否过于严格?

这是一个不同的问题,不是关于您的示例代码.是的,要求POD-ness太严格了.在C++ 0x中,这被认可,并且给出了一个更宽松的新要求"标准布局".我认为,这两个complex complex_base是标准的布局类,由C++ 0x中定义.C++ 0x规范说,而不是你引用的文字:

指向标准布局结构对象的指针,使用reinterpret_cast进行适当转换,指向其初始成员(或者如果该成员是位字段,则指向它所在的单元),反之亦然.

我将其解释为允许将指针转换为a double,实际指向complex成员(通过继承成员),将其转换为a complex*.标准布局类是没有包含非静态数据的基类,或者只有一个包含非静态数据的基类的类.因此,有一个独特的"初始成员".