如何访问object representation?为了回答这个问题,我将其分为两个问题:
根据标准,我看不到任何方法来获取指向对象表示的指针。人们经常建议这样做:
some_type obj{};
const char * rep = reinterpret_cast<const unsigned char*>(&obj);
尽管如此,标准中并未说明对象及其对象表示是指针可互换的。为什么标准允许这个代码?
some_type obj{};
const char * rep = reinterpret_cast<const unsigned char*>(&obj);
char x = rep[0] + rep[1];
此处obj
默认初始化。编译器如何解释rep[0]
,它是 indeterminate-value ,还是可能取决于obj
初始化期间已初始化的内存字节数?
答案 0 :(得分:2)
使用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,它是 指定对象
这是由值表示的定义引起的,与内存模型和对象生命周期一起。
但是,您的示例更复杂:
rep[0]
尽管此属性仍然是未确定的值,如果它仅由填充位组成。在您的示例中就是这种情况,因为对象的大小至少为1,但由于您没有成员,因此值表示为空。 rep[1]
可以是未定义的行为,如果sizeof(some_type)<2
,因为取消引用传递给数组的最后一个元素的指针是UB。 我们举一个简单的例子:
class some_other_type {
int a;
std::string s;
};
在谈论对象占用的内存时存在歧义:
int
,字符串长度的某些size_t
和字符串中的字符的一些指针,如它将在C)完成? 对象表示对应于第一部分。对于非平凡可复制的对象,对象表示不是自给自足的(即在我们的示例中,存储在字符串中的字节不一定是对象表示的一部分)。
值表示对应于第二部分(并且将包括存储字符串值所需的字节)。
简单来说,这意味着对象的地址是其表示的地址,但对象表示可能包含填充,可能不足以容纳属于该对象的每个数据。