reinterpret_cast几乎pod数据(足够布局兼容性) [英] reinterpret_cast for almost pod data (is layout-compatibility enough)

查看:190
本文介绍了reinterpret_cast几乎pod数据(足够布局兼容性)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想了解 static_cast reinterpret_cast



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



< blockquote>

指向使用
reinterpret_cast 适当转换的POD结构体对象
的指针指向
初始成员(或者如果该成员是
位字段,则其驻留在
中的单元),反之亦然。 [注意:因此,为了实现
适当的对齐,可能在POD结构体对象内填充未命名的
,而不是在它的开始。 - end
note]


我的问题是如何严格解释这个问题。例如,布局兼容性够吗?

对我来说,下面的例子显示了一个严格的只有POD是有效的解释似乎是错误的例子。

  class complex_base //一个POD类(我相信)
{
public:
double m_data [ 2]。
};

class complex:public complex_base
{//不是POD类(由于构造函数和继承)
public:
complex(const double real,const double imag);
}

double * d = new double [4];
//我相信以下是有效的,因为complex_base是POD
complex_base& cb1 = reinterpret_cast< complex_base&>(d [0]);
complex_base& cb2 = reinterpret_cast< complex_base&>(d [2]);
//下面是否完成一个有效的转换,即使复杂不是POD?
complex& c1 = static_cast< complex&>(cb1);
complex& c2 = static_cast< complex&>(cb2);

此外,如果 complex_base :: m_data 是protected(意味着 complex_base 不是pod)?



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



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

解决方案


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


d [0] 不指向 complex_base 对象的第一个成员。它的对齐可能因此对于 complex_base 对象不够好,因此这样的转换是不安全的(并且不被您引用的文本所允许)。


下面是否完成一个有效的转换,即使复杂不是POD?


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


如果类型cv1 B的左值实际上是一个对象的子对象类型D,lvalue指的是类型D的包围对象。否则,转换的结果是未定义的。


如果只是涉及的类型合在一起是不够的。文本谈论指向一个POD结构对象的指针和一个引用某个子对象的左值。
oth complex和complex_base是标准布局对象。 C ++ 0x规格说,而不是你引用的文本:



POD-ness要求是否太严格?



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


指向标准布局结构体对象的指针, reinterpret_cast,指向其初始成员(或者如果该成员是位字段,则指向它所驻留的单元),反之亦然。


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


I am trying to learn about static_cast and reinterpret_cast.

If I am correct the standard (9.2.18) says that reinterpret_cast for pod data is safe:

A pointer to a POD-struct object, suitably converted using a reinterpret_cast, points to its initial member (or if that member is a bit-field, then to the unit in which it resides) and vice versa. [ Note: There might therefore be unnamed padding within a POD-struct object, but not at its beginning, as necessary to achieve appropriate alignment. — end note ]

My question is how strictly to interpret this. Is, for example, layout-compatibility enough? and if not, why not?

To me, the following example shows an example where a strict 'only POD is valid' interpretation seems to be wrong.

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);

Also, what can possibly break if complex_base::m_data is protected (meaning that complex_base is not pod)? [EDIT: and how do I protect myself/detect such breakages]

It seems to me that layout-compatibility should be enough - but this does not seem to be what the standard says.

EDIT: Thanks for the answers. They also helped me find this, http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2342.htm

解决方案

I believe the following are valid because complex_base is POD

You are wrong. d[0] does not refer to the first member of a complex_base object. Its alignment may therefor not be good enough for a complex_base object, therefor such a cast is not safe (and not allowed by the text you quote).

Does the following complete a valid cast to complex even though complex is NOT POD?

cb1 and cb2 do not point to subobjects of an object of type complex, therefor the static_cast produces undefined behavior. Refer to 5.2.9p5 of C++03

If the lvalue of type "cv1 B" is actually a sub-object of an object of type D, the lvalue refers to the enclosing object of type D. Otherwise, the result of the cast is undefined.

It's not enough if merely the types involved fit together. The text talks about a pointer pointing to a POD-struct object and about an lvalue referring to a certain subobject. oth complex and complex_base are standard-layout objects. The C++0x spec says, instead of the text you quoted:

Is POD-ness requirement too strict?

This is a different question, not regarding your example code. Yes, requiring POD-ness is too strict. In C++0x this was recognized, and a new requirement which is more loose, "standard-layout" is given. I do think that both complex and complex_base are standard-layout classes, by the C++0x definition. The C++0x spec says, instead of the text you quoted:

A pointer to a standard-layout struct object, suitably converted using a reinterpret_cast, points to its initial member (or if that member is a bit-field, then to the unit in which it resides) and vice versa.

I interpret that as allowing to cast a pointer to a double, which actually points to a complex member (member by inheritance), to be casted to a complex*. A Standard-layout class is one that either has no base classes containing non-static data, or has only one base-class containing non-static data. Thus there is an unique "initial member".

这篇关于reinterpret_cast几乎pod数据(足够布局兼容性)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆