C++ 标准的当前草案(2019 年 3 月)有以下段落([basic.types] p.4)(强调我的):
T 类型对象的对象表示是 T 类型对象占用的 N 个 unsigned char 对象的序列,其中 N 等于 sizeof(T)。
T 类型对象的值表示是参与表示 T 类型值的一组位。
对象表示中不属于值表示的位是填充位。对于普通可复制类型,值表示是对象表示中确定值的一组位,该值是实现定义的一组值的一个离散元素.
为什么突出显示的句子仅限于可以简单地复制类型?是因为一些位值表示 of a 不可平凡复制对象可能在其之外对象表示? 这个答案 https://stackoverflow.com/a/46736040/3766405, 也this one https://stackoverflow.com/a/12773681/3766405暗示这个。
然而,在上面链接的答案中,概念性的value对象的语义基于用户引入的语义。在第一个链接答案的示例中:
class some_other_type
{
int a;
std::string s;
};
用户决定value类型对象的some_other_type
包括属于字符串的字符s
.
我试图想一些例子,说明对象的某些部分(不是可以简单地复制) 值表示都在其之外对象表示是隐式的(实现必须这样做,不是由用户随意决定的)。
我想到的一个例子是值表示具有虚方法的基类子对象可以包括来自对象表示它所属的完整对象的属性,因为与它本身是完整对象的情况相比,基类子对象的行为可能不同(可能“具有不同的值”)。
我想到的另一个例子是vtable也可能是其中的一部分值表示的对象的虚拟表指针指向它。
这些例子正确吗?还有其他例子吗?
标准委员会引入突出显示的句子是因为对象的语义“值”可能由用户决定(如两个链接的答案中所示),还是因为实现可能决定(或者可能是)被迫)这样做,或两者兼而有之?
谢谢。
按照我的理解,你强调的这句话的重点是这一部分:
对于普通可复制类型,值表示是一组位在对象表示中它确定一个值,该值是实现定义的一组值的一个离散元素。
本质上,标准的 [basic.types]#4 表示“每个对象都有一组位O
这是它的对象表示和一组作为其值表示的位V
。套装P = O without V
是填充位。对于普通可复制类型,V
是一个子集O
”。后者很重要,因为它意味着围绕O
位组也可以安全地复制V
对于普通可复制类型,因此保留该值。你如何定义V
对于其他类型在这里无关紧要(如果需要,请将其设置为整个抽象机)。
回答评论中提出的修改后的问题:
如果 1110000100010001111 是不可平凡复制对象的对象表示,为什么实现不能告诉它意味着什么?是否因为还有一些其他位(在此对象表示之外)可以帮助确定对象具有什么值?
让我们来std::string
举个例子。它不是可简单复制的,因为它必须处理内存管理。
If two std::string
对象具有相同的位模式,它们意味着相同的事情吗?
没有。有至少一个实现 https://stackoverflow.com/questions/55181063/weird-behavior-in-struct-destruction/55182495#55182495通过使其缓冲区指针指向自身(gcc)来指示小字符串优化。销毁后,当(且仅当)缓冲区未指向该确切位置时,缓冲区才会被释放。
显然,两个std::string
驻留在不同位置的对象必须(在此实现中)表示相同的(小)字符串值不同的位模式(缓冲区指针必须不同)。更重要的是,两个对象中的相同位模式可能意味着非常不同的事情 - 它可能在一种情况下指示 SSO,但在另一种情况下则不然。
正如您所看到的,每个值的表示都有附加信息参与std::string
这里:它在内存中的位置(即this
)。标准没有进一步规定如何用位来表示。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)