C++标准的当前草案(2019年3月)具有以下段落([basic.types] p.4)(强调我的):



为什么突出显示的句子仅限于平凡可复制的类型?是因为不可平凡对象的值表示形式中的某些位可能不在其对象表示形式之外? This answer以及this one都暗示了这一点。

但是,在上面链接的答案中,对象的概念值(value)基于用户引入的语义。在第一个链接的答案的示例中:

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

用户确定some_other_type类型的对象的值包含属于字符串s的字符。

我试图考虑一些示例,其中某个对象的值表示(某些不可复制的值)的某些位不在其对象表示之内的事实是隐式的(实现必须这样做,它不是由用户任意决定的)。

我想到的一个例子是,使用虚拟方法的基类子对象的值表示形式可能包含其所属完整对象的对象表示形式中的位,因为基类子对象的行为可能有所不同(可能“具有一个不同的值”),相比之下,它本身就是一个完整的对象。

尽管我想到的另一个例子是,vtable也可能是其vtable指针指向它的对象的值表示的一部分。

这些例子正确吗?还有其他例子吗?

是标准委员会引入突出显示的句子,是因为对象的语义“值”可能由用户决定(如在两个链接的答案中一样),或者由于实现方式可能决定(或可能是强制执行此操作,或两者都执行?

谢谢你。

最佳答案

在我的解释中,您突出显示的句子的重点是以下部分:



本质上,该标准的[basic.types]#4表示“每个对象都有一组O位,分别是其对象表示形式和一组位,其值表示形式V。该组P = O without V是填充位。可复制类型,VO的子集“”。后者很重要,因为这意味着对于琐碎可复制的类型,在O位集合周围进行复制也可以安全地在V附近进行复制,从而保留了该值。在此,如何定义其他类型的V无关紧要(如果需要,可以将其设置为整个抽象机)。

要回答评论中提出的修改后的问题,请执行以下操作:



让我们以std::string为例。它不可复制,因为它必须处理内存管理。

如果两个std::string对象具有相同的位模式,那么它们的意思相同吗?

否。at least one implementation通过使其缓冲区指针指向自身(gcc)来指示小字符串优化。销毁后,如果(且仅当)缓冲区未指向该确切位置时,才将其释放。

显然,驻留在不同位置的两个std::string对象将必须(在此实现中)表示具有不同位模式的相同(较小)字符串值(缓冲区指针必须不同)。更重要的是,两个对象中相同的位模式可能意味着截然不同的事物-在一种情况下可能表示SSO,而在另一种情况下则未表示SSO。

如您所见,此处每个std::string的值表示形式都包含其他信息:它在内存中的位置(即this的值)。该标准没有进一步规定以位表示的精确度。

关于非平凡可复制类型的C++值表示形式,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55225535/

10-13 08:29