You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++14中Placement new结合reinterpret_cast是否合规?

C++14对齐存储对象访问的合法性解析

原代码的合法性与严格别名规则判断

先看你给出的C++14代码:

alignas(T) unsigned char data[sizeof(T)];
new (data) T();
T* p = reinterpret_cast<T*>(data);
p->something();  // UB?

这段代码在C++14中完全合法,不存在违反严格别名规则的问题。

标准依据

C++14标准的[basic.lval]条款明确了严格别名规则的例外情况:

  • 允许用char或unsigned char类型的glvalue访问任何对象的底层字节;反之,当你通过placement new在unsigned char数组的存储位置上构造了一个T类型的对象后,该存储位置的实际对象类型已变为T,此时用reinterpret_cast将unsigned char*转换为T*并访问这个T对象,完全符合标准要求——因为你是通过与对象实际类型匹配的glvalue来访问它的。

C17的std::launder要求对C14的影响

再看cppreference上的示例代码:

// Access an object in aligned storage
const T& operator[](std::size_t pos) const
{
    // Note: std::launder is needed after the change of object model in P0137R1
    return *std::launder(reinterpret_cast<const T*>(&data[pos]));
}

C++17通过P0137R1修订了对象模型,引入了更严格的“对象身份”规则:即使你在unsigned char数组的存储位置上构造了新的T对象,编译器可能仍会认为该位置的对象还是原来的unsigned char数组,直接用reinterpret_cast得到的T*访问可能被编译器优化(视为无效指针),因此必须用std::launder告知编译器该指针指向的是一个新构造的对象,需要重新识别其身份。

但在C++14中,并没有这样的对象模型修改。编译器会承认在unsigned char数组存储位置上构造的T对象的身份,因此不需要std::launder,直接转换后访问是安全的,不会触发未定义行为。

内容的提问来源于stack exchange,提问作者user1011113

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 16:35:09