Adr*_*ian -1 c++ placement-new
我正在构建一个将在类中使用的缓冲区,并想知道以下内容根据 C++ 标准是否有效:
#include <iostream>
#include <cstdint>
int main() {
alignas(std::int32_t) char A[sizeof(std::int32_t)] = { 1, 0, 0, 0 };
std::int32_t* pA = new (&A) std::int32_t;
std::cout << *pA << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
缓冲区已初始化为char4 字节数组。在结构顶部进行新的放置是否允许我访问下面的位int32_t?我现在可以在不违反标准的情况下以 4char秒(通过buffer对象)或 1 int32_t(通过)访问那里的内存空间吗?pA如果不行,是否可以采取其他方式?
注意:是的,我知道字节序,但在这种情况下,字节序并不重要。这是一个不同的讨论。
(为简洁起见,假设int和int32_t是同一类型)
在C++20中,由于A是一个字符数组,因此int可以在 中隐式创建类型的对象A,因此只需要以下内容:
alignas(int) char A[sizeof(int)] = { 1, 0, 0, 0 };
int * pA = reinterpret_cast<int*>(&A[0]);
std::cout << *pA << std::endl;
Run Code Online (Sandbox Code Playgroud)
原始对象的问题new (&A) int在于它结束了char[sizeof(int)]初始化的原始对象的生命周期,因此无法读取其值。现在您有了一个 default-initialized int,可以读取 UB 。因此,您的原始代码相当于:
int A;
std::cout << A << std::endl;
Run Code Online (Sandbox Code Playgroud)
如果您不能依赖 C++ 20 隐式对象创建,则可以使用类型双关方法,该方法创建具有相同“位模式”(值表示)的不同类型的对象。std::bit_cast(或者使用 实现的版本std::memcpy)可以使用:
char A[sizeof(int)] = { 1, 0, 0, 0 };
int B = std::bit_cast<int>(A);
std::cout << B << std::endl;
Run Code Online (Sandbox Code Playgroud)
或者std::memcpy直接复制值表示:
int A;
std::cout << A << std::endl;
Run Code Online (Sandbox Code Playgroud)
您可以A使用placement new 来更改from char[sizeof(int)]to的有效类型int,如下所示:
char A[sizeof(int)] = { 1, 0, 0, 0 };
int B = std::bit_cast<int>(A);
std::cout << B << std::endl;
Run Code Online (Sandbox Code Playgroud)