“提供存储”是否意味着成为“对象表示”?

问题描述 投票:0回答:1

考虑这段代码:

auto buffer = new unsigned char[MAX_LEN];
auto hdr1 = new (buffer) Header1{ /* ... */ };
size_t pos1 = sizeof(Header1);
auto hdr2 = new (buffer + pos1) Header2{ /* ... */ };
size_t pos2 = pos1 + sizeof(Header2);
hdr2->data_len = fread(buffer + pos2, 1, MAX_LEN - pos2, stdin);
network_sendto(peer, buffer, pos2 + hdr2->data_len);

该代码的目的是将 Header1 的对象表示形式发送到网络,然后是 Header2 的对象表示形式,最后是用户数据。

当前标准是这么说的([basic.types.general]):

完整对象类型 T对象表示 是由 T 类型的非位域完整对象占用的

N
unsigned char 对象序列,其中 N 等于
sizeof(T)
。类型T值表示是……类型T的非位域完整对象的对象和值表示分别是该对象对应的字节和位其类型的对象和值表示。 ......

如果我理解正确的话,一旦缓冲区为 Header 提供存储,其中的一部分(“N

unsigned char
对象的序列”)会自动成为 Header 的对象表示。所以我认为代码是有效的。 这个答案末尾的代码示例似乎也同意。

  1. 以上推理正确吗?代码在某些方面是否表现出 UB?
  2. 我还想知道如果P1839进入标准,它是否仍然有效。因为那篇论文似乎触及了对象表示的定义。
c++ language-lawyer placement-new type-punning
1个回答
0
投票

我可以看到如何阅读该标准来暗示当

unsigned char
数组为对象提供存储时,那么与该对象占用相同存储空间的数组元素就是对象表示。然而,我不认为这就是它的真正含义。每个完整的对象都应该有一个符合 [basic.types.general]/4 的对象表示,包括那些没有放置在
unsigned char
缓冲区中的对象。这表明对象表示本质上是附属于一个完整对象的东西,而为其提供存储的数组是偶然的。该标准没有解释如何访问对象表示(P1839 旨在解决此问题),也没有指定在访问为对象提供存储的缓冲区元素时获得的值。 (如果我们从字面上理解标准,当将对象构造到缓冲区中或修改该对象时,数组的内容不会改变,因为没有规则会使数组元素的值改变,但是这显然是不对的。)

P1839 也没有说明提供存储的数组的内容。在 P1839 中,对象表示被明确声明为数组,但该数组是一个单独的对象,与提供存储的数组重叠(如果后者存在)。

© www.soinside.com 2019 - 2024. All rights reserved.