我的程序通过网络接收消息.这些消息被一些中间件(即其他人无法更改的代码)反序列化.我的程序接收到如下所示的对象:
struct Message {
int msg_type;
std::vector<uint8_t> payload;
};
Run Code Online (Sandbox Code Playgroud)
通过检查,msg_type我可以确定消息有效负载实际上是,例如,uint16_t值数组.我想在没有不必要的副本的情况下读取该数组.
我的第一个想法是这样做:
const uint16_t* a = reinterpret_cast<uint16_t*>(msg.payload.data());
Run Code Online (Sandbox Code Playgroud)
但是阅读a似乎违反了标准.这是第3.10.10条:
如果程序试图通过以下类型之一以外的glvalue访问对象的存储值,则行为未定义:
- 对象的动态类型,
- 一个cv限定版本的动态类型的对象,
- 与对象的动态类型类似的类型(如4.4中所定义),
- 与对象的动态类型对应的有符号或无符号类型的类型,
- 一种类型,是有符号或无符号类型,对应于对象动态类型的cv限定版本,
- 聚合或联合类型,包括其元素或非静态数据成员中的上述类型之一(递归地,包括子聚合或包含联合的元素或非静态数据成员),
- 一个类型,它是对象动态类型的(可能是cv限定的)基类类型,
- a
char或unsigned char类型.
在这种情况下,a将是glvalue并且uint16_t*似乎不符合任何列出的标准.
那么如何在uint16_t不调用未定义的行为或执行不必要的副本的情况下将有效负载视为值数组?
放置new的返回值与其操作数的转换值之间是否存在(语义)差异?
struct Foo { ... };
char buffer[...];
Foo *a = new(buffer) Foo;
Foo *b = reinterpret_cast<Foo *>(buffer);
Run Code Online (Sandbox Code Playgroud)
是否a和b以某种方式有什么不同?
编辑:根据DaBler的评论,这个问题告诉我,如果使用const/reference成员则存在差异:使用const成员放置新类和赋值
所以,我的小位的更新问题:是否a和b以任何方式不同,如果Foo没有const或引用成员?
c++ strict-aliasing placement-new language-lawyer reinterpret-cast