gpt4 book ai didi

c++ - Placement new 的返回值与其操作数的强制转换值之间是否存在(语义)差异?

转载 作者:IT老高 更新时间:2023-10-28 21:44:25 25 4
gpt4 key购买 nike

placement new 的返回值与其操作数的强制转换值之间是否存在(语义)差异?

struct Foo { ... };
char buffer[...];

Foo *a = new(buffer) Foo;
Foo *b = reinterpret_cast<Foo *>(buffer);

ab 有什么不同吗?


编辑:根据 DaBler 的评论,如果使用 const/reference 成员,这个问题表明存在差异:Placement new and assignment of class with const member

所以,我的一点更新问题:ab 是否有任何不同,如果 Foo 没有 const 或引用成员?

最佳答案

仅限 a可以安全地用于直接访问 Foo由放置 new-expression 创建的对象(为了便于引用,我们将其称为 x)。使用 b需要 std::launder .

a 的值在 [expr.new]/1 中指定:

If the entity is a non-array object, the result of the new-expression is a pointer to the object created.

a 的值因此是“指向 x 的指针”。当然,这个指针可以安全地用于访问 x .

reinterpret_cast<Foo*>(buffer)将数组到指针的转换应用于 buffer (见 [expr.reinterpret.cast]/1)。应用转换后的结果值为“指向buffer 的第一个元素的指针”。这是 reinterpret_cast一个对象指针指向不同类型的对象指针,定义为等价于 static_cast<Foo*>(static_cast<void*>(buffer))[expr.reinterpret.cast]/7 .

内投到void*实际上是一种隐式转换。根据 [conv.ptr]/2 ,

The pointer value is unchanged by this conversion.

因此,内部转换产生 void*值为“指向buffer的第一个元素的指针”。

外部 Actor 由 [expr.static.cast]/13 管理,我已将其重新格式化为要点:

A prvalue of type “pointer to cv1 void” can be converted to a prvalue of type “pointer to cv2 T”, where T is an object type and cv2 is the same cv-qualification as, or greater cv-qualification than, cv1.

  • If the original pointer value represents the address A of a byte in memory and A does not satisfy the alignment requirement of T, then the resulting pointer value is unspecified.

  • Otherwise, if the original pointer value points to an object a, and there is an object b of type T (ignoring cv-qualification) that is pointer-interconvertible with a, the result is a pointer to b.

  • Otherwise, the pointer value is unchanged by the conversion.

假设 buffer适当对齐(如果不是,那么在此之前你会遇到麻烦),第一个项目符号不适用。第二个项目符号同样不适用,因为没有 pointer-interconvertiblity这里。因此,我们击中了第三个项目符号 - “指针值不会因转换而改变”,并且仍然是“指向 buffer 的第一个元素的指针”。

因此,b不指向 Foo对象 x ;它指向第一个 char buffer 的元素, 即使它的类型是 Foo* .因此它不能用于访问 x ;尝试这样做会产生未定义的行为(对于非静态数据成员的情况,[expr.ref] 的省略;对于非静态成员函数的情况,[class.mfct.non-static]/2 的省略)。

恢复指向 x 的指针来自 b , std::launder可以使用:

b = std::launder(b); // value of b is now "pointer to x"
// and can be used to access x

关于c++ - Placement new 的返回值与其操作数的强制转换值之间是否存在(语义)差异?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47653305/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com