有一些共识,即由于混叠规则C++,您不能随意将(int*)指向char
数组。
从另一个问题 - 基于通用字符[]的存储并避免与严格混叠相关的UB - 似乎允许通过放置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++是否真的需要新的安置才能使其合法化?
是的,放置new
是必需的,否则您将违反严格的别名(分配是访问权限)。
以上合法吗?几乎(尽管它几乎适用于所有实现)。通过强制转换创建的指针不指向对象,因为(现已销毁)数组和int
对象不是指针可相互转换的;使用 std::launder((int*)buf)
,或者更好的是,使用放置new
的返回值。
随着 P0593R6 引入隐式生存期类型(作为缺陷报告,因此这适用于所有C++版本),这种情况发生了变化。
alignas(int) char buf[sizeof(int)];
开始 char 数组的生存期 char[sizeof(int)]
。这也将隐式启动您在表达式*((int*)buf) = 42
中访问的int
对象的生存期。
从 C++17 开始,您还需要清洗指针:*std::launder((int*)buf) = 42
.
*((int*)buf) = 42;
使用 int
左值写入int
,因此首先没有混叠问题。