如何根据c ++标准访问对象表示?

时间:2017-10-13 17:41:07

标签: c++ pointers object language-lawyer undefined-behavior

如何访问object representation?为了回答这个问题,我将其分为两个问题:

1。如何获得指向对象表示的指针?

根据标准,我看不到任何方法来获取指向对象表示的指针。人们经常建议这样做:

some_type obj{};
const char * rep = reinterpret_cast<const unsigned char*>(&obj);

尽管如此,标准中并未说明对象及其对象表示指针可互换的。为什么标准允许这个代码?

2。我们可以考虑在初始化对象时初始化对象表示吗?

some_type obj{};
const char * rep = reinterpret_cast<const unsigned char*>(&obj);
char x = rep[0] + rep[1];

此处obj默认初始化。编译器如何解释rep[0],它是 indeterminate-value ,还是可能取决于obj初始化期间已初始化的内存字节数?

1 个答案:

答案 0 :(得分:2)

1)您的方法有效:

使用const指针确保constness不会被丢弃:

  

5.2.10 / 2 reinterpret_cast运算符不应抛弃constness。

指针转换是安全的,因为char没有比some_type更严格的对齐要求,因此您可以将rep转换回some_type*

  

5.2.10 / 7 可以将对象指针显式转换为不同类型的对象指针。 (...)转换类型的prvalue   “指向T1的指针”到“指向T2的指针”(其中T1和T2为   对象类型以及T2的对齐要求为否   比T1更严格,并回到原来的类型产生   原始指针值。

编辑在我的理解中,毫无疑问指向对象的指针与指向其表示的指针之间的可互换性:

  

1.8 / 6:除非对象是零字段或零大小的基类子对象,否则该对象的地址是第一个的地址   它占据的字节。

     

3.9 / 4:类型为T 的对象的对象表示形式是对象占用的N个无符号字符对象的序列 T型,   其中N等于sizeof(T)。

我理解&#34;接受&#34;是&#34;占据&#34;的同义词。另请注意,&运算符保证:

  

5.3.1 / 3:(...)如果表达式的类型为T,则结果的类型为“指向T的指针”,并且是一个prvalue,它是   指定对象

2)使用对象

初始化对象表示

这是由值表示的定义引起的,与内存模型和对象生命周期一起。

但是,您的示例更复杂:

  • rep[0]尽管此属性仍然是未确定的值,如果它仅由填充位组成。在您的示例中就是这种情况,因为对象的大小至少为1,但由于您没有成员,因此值表示为空。
  • rep[1]可以是未定义的行为,如果sizeof(some_type)<2,因为取消引用传递给数组的最后一个元素的指针是UB。

3)对象表示是什么(用简单语言)?

我们举一个简单的例子:

class some_other_type {
    int a;
    std::string s;
};

在谈论对象占用的内存时存在歧义:

  • 只是与其类型对应的固定大小的连续内存(即int,字符串长度的某些size_t和字符串中的字符的一些指针,如它将在C)完成?
  • 或者是存储在对象的内存中的所有值,包括存储在其他地方分配的内存位置的某些值(例如,还有存储字符串值所需的字节)?

对象表示对应于第一部分。对于非平凡可复制的对象,对象表示不是自给自足的(即在我们的示例中,存储在字符串中的字节不一定是对象表示的一部分)。

值表示对应于第二部分(并且将包括存储字符串值所需的字节)。

简单来说,这意味着对象的地址是其表示的地址,但对象表示可能包含填充,可能不足以容纳属于该对象的每个数据。