c++ 将int放入char数组中是否需要placement new?

ttisahbt  于 2023-02-06  发布在  其他
关注(0)|答案(3)|浏览(169)

由于C++的别名规则,你不能随意地将(一个int*)指向char数组,这似乎是一个共识。
从另一个问题--Generic char[] based storage and avoiding strict-aliasing related UB--来看,似乎允许通过placement new(重新)使用存储。

alignas(int) char buf[sizeof(int)];

void f() {
  // turn the memory into an int: (??) from the POV of the abstract machine!
  ::new (buf) int; // is this strictly required? (aside: it's obviously a no-op)

  // access storage:
  *((int*)buf) = 42; // for this discussion, just assume the cast itself yields the correct pointer value
}

那么,上面的C++ * 和 * 是合法的吗?要使它合法,实际上需要新的放置吗?

3htmauhk

3htmauhk1#

是的,放置new是必要的,否则您将违反严格的别名(赋值为access)。
以上是法律的的吗?几乎是合法的(尽管它实际上对所有的实现都有效).通过强制转换创建的指针并不指向对象,因为(现在已销毁的)数组和int对象是不可指针互换的;使用std::launder((int*)buf),或者更好的是,使用布局new的返回值。

ndh0cuux

ndh0cuux2#

随着P0593R6引入隐式生存期类型(作为缺陷报告,因此这适用于所有C版本),这一点发生了变化。
alignas(int) char buf[sizeof(int)];启动char数组char[sizeof(int)]的生存期。这也将隐式启动在表达式*((int*)buf) = 42中访问的int对象的生存期。
从C
17开始,你还需要清洗指针:*std::launder((int*)buf) = 42 .

jmp7cifd

jmp7cifd3#

*((int*)buf) = 42;

使用int左值写入int,因此首先不存在混叠问题。

相关问题