使用 placement new 会使以下代码有效吗?

Would using placement new make the following code valid?

我正在构建一个将在 class 中使用的缓冲区,并想知道根据 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;
}

缓冲区已初始化为 char 4 字节数组。在结构顶部做一个新的放置是否允许我以 int32_t 的形式访问下面的位?我现在可以访问内存 space 作为 4 chars(通过 buffer 对象)或作为 1 int32_t(通过 pA)而不违反标准?如果不行,是否可以采取其他方式?

注意:是的,我知道字节序,但在这种情况下,字节序并不重要。那是一个不同的讨论。

(为简洁起见,假设 intint32_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;

您原来的 new (&A) int 的问题在于它结束了初始化的原始 char[sizeof(int)] 对象的生命周期,因此无法读取其值。你现在有一个默认初始化的 int,这是 UB 读取。因此,您的原始代码相当于:

int A;
std::cout << A << std::endl;

如果您不能依赖 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;

std::memcpy直接复制值表示:

char A[sizeof(int)] = { 1, 0, 0, 0 };
int B;
std::memcpy(&B, A, sizeof(int));
std::cout << B << std::endl;

可以使用placement new将A的有效类型从char[sizeof(int)]更改为int,像这样:

alignas(int) char A[sizeof(int)] = { 1, 0, 0, 0 };
// `A` has effective type `char[sizeof(int)]`; cannot be accessed through `int*`

int * pA = new (&A) int(std::bit_cast<int>(A));
// `A` now has effective type `int`. This line should be optimised to do nothing to `A` at runtime.

std::cout << *pA << std::endl;

// Or using `A` directly
std::cout << *std::launder(reinterpret_cast<int*>(A)) << std::endl;