由于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++ * 和 * 是合法的吗?要使它合法,实际上需要新的放置吗?
3条答案
按热度按时间3htmauhk1#
是的,放置
new
是必要的,否则您将违反严格的别名(赋值为access)。以上是法律的的吗?几乎是合法的(尽管它实际上对所有的实现都有效).通过强制转换创建的指针并不指向对象,因为(现在已销毁的)数组和
int
对象是不可指针互换的;使用std::launder((int*)buf)
,或者更好的是,使用布局new
的返回值。ndh0cuux2#
随着P0593R6引入隐式生存期类型(作为缺陷报告,因此这适用于所有C版本),这一点发生了变化。
alignas(int) char buf[sizeof(int)];
启动char数组char[sizeof(int)]
的生存期。这也将隐式启动在表达式*((int*)buf) = 42
中访问的int
对象的生存期。从C17开始,你还需要清洗指针:
*std::launder((int*)buf) = 42
.jmp7cifd3#
使用
int
左值写入int
,因此首先不存在混叠问题。