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

2023-12-10

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

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

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

Does a and b在某些方面有所不同?


编辑:根据 DaBler 的评论,这个问题表明,如果使用 const/reference 成员,则存在差异:新的放置和 const 成员的类分配

所以,我更新了一点问题:a and b无论如何,如果Foo没有 const 或引用成员?


Only a可以安全地用于直接访问Foo由放置创建的对象新表达(我们称之为x以便于参考)。使用b需要std::launder.

的价值a指定于[expr.new]/1:

如果实体是非数组对象,则结果新表达是指向所创建对象的指针。

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

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

内部演员阵容void*实际上是隐式转换。每[转化指针]/2,

此转换不会改变指针值。

因此,内部铸件产生void*值为“指向第一个元素的指针buffer".

外部演员受制于[expr.static.cast]/13,我将其稍微重新格式化为要点:

“指向的指针”类型的纯右值cv1 void” 可以转换为“指向的指针”类型的纯右值cv2 T“, 在哪里T是一个对象类型并且cv2简历资格与以下相同或更高:cv1.

  • 如果原始指针值代表地址A内存中的一个字节和A不满足对齐要求T, 那么结果指针值是未指定的。

  • 否则,如果原始指针值指向一个对象a,并且有一个对象b类型的T(忽略简历资格) 这是指针可相互转换的a,结果是一个指向b.

  • 否则,指针值不会因转换而改变。

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

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

恢复指向x from b, std::launder可以使用:

b = std::launder(b); // value of b is now "pointer to x"
                     // and can be used to access x
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

放置 new 的返回值与其操作数的强制转换值之间是否存在(语义)差异? 的相关文章

  • 未提供参数时如何指定 C# System.Commandline 行为?

    在我的控制台应用程序中 当未提供控制台参数时 将执行我指定列表 在本例中为参数 3 的任何处理程序 调用该处理程序时 布尔参数设置为 false 但对我来说 根本不调用它更有意义 如何防止这种情况发生并显示帮助文本 using System
  • 提交后禁用按钮

    当用户提交付款表单并且发布表单的代码导致 Firefox 中出现重复发布时 我试图禁用按钮 去掉代码就不会出现这个问题 在firefox以外的任何浏览器中也不会出现这个问题 知道如何防止双重帖子吗 System Text StringBui
  • 当我们想要返回对象的引用时,为什么我们在赋值运算符中返回 *this 而通常(而不是 this)?

    我正在学习 C 和指针 我以为我理解了指针 直到我看到这个 一方面 asterix 运算符是解引用的 这意味着它返回值所指向的地址中的值 而与号 运算符则相反 它返回值存储的地址记忆 现在阅读有关赋值重载的内 容 它说 我们返回 this因
  • 为什么极端下派生类(多重虚拟继承)的大小包括超类成员大小的两倍?

    include
  • 如何创建包含 IPv4 地址的文本框? [复制]

    这个问题在这里已经有答案了 如何制作一个这样的文本框 我想所有的用户都见过这个并且知道它的功能 您可以使用带有 Mask 的 MaskedTestBox000 000 000 000 欲了解更多信息 请参阅文档 http msdn micr
  • 使用接口有什么好处?

    使用接口有什么用 我听说它用来代替多重继承 并且还可以用它来完成数据隐藏 还有其他优点吗 哪些地方使用了接口 程序员如何识别需要该接口 有什么区别explicit interface implementation and implicit
  • 在 Visual Studio 2010 中从 Fortran 调用 C++ 函数

    我想从 Fortran 调用 C 函数 为此 我在 Visual Studio 2010 中创建了一个 FORTRAN 项目 之后 我将一个 Cpp 项目添加到该 FORTRAN 项目中 当我要构建程序时出现以下错误 Error 1 unr
  • qdbusxml2cpp 未知类型

    在使用 qdbusxml2cpp 程序将以下 xml 转换为 Qt 类时 我收到此错误 qdbusxml2cpp c ObjectManager a ObjectManager ObjectManager cpp xml object ma
  • 使用自定义堆的类似 malloc 的函数

    如果我希望使用自定义预分配堆构造类似 malloc 的功能 那么 C 中最好的方法是什么 我的具体问题是 我有一个可映射 类似内存 的设备 已将其放入我的地址空间中 但我需要获得一种更灵活的方式来使用该内存来存储将随着时间的推移分配和释放的
  • C#:帮助理解 UML 类图中的 <>

    我目前正在做一个项目 我们必须从 UML 图编写代码 我了解 UML 类图的剖析 但我无法理解什么 lt
  • 等待进程释放文件

    我如何等待文件空闲以便ss Save 可以用新的覆盖它吗 如果我紧密地运行两次 左右 我会得到一个generic GDI error
  • AES 128 CBC 蒙特卡罗测试

    我正在 AES 128 CBC 上执行 MCT 如中所述http csrc nist gov groups STM cavp documents aes AESAVS pdf http csrc nist gov groups STM ca
  • 如何设置 log4net 每天将我的文件记录到不同的文件夹中?

    我想将每天的所有日志保存在名为 YYYYMMdd 的文件夹中 log4net 应该根据系统日期时间处理创建新文件夹 我如何设置它 我想将一天中的所有日志保存到 n 个 1MB 的文件中 我不想重写旧文件 但想真正拥有一天中的所有日志 我该如
  • 如何在非控制台应用程序中查看 cout 输出?

    输出到调试窗口似乎相当繁琐 我在哪里可以找到cout如果我正在编写非控制台信息 则输出 Like double i a b cout lt lt b lt lt endl I want to check out whether b is z
  • 使用 %d 打印 unsigned long long

    为什么我打印以下内容时得到 1 unsigned long long int largestIntegerInC 18446744073709551615LL printf largestIntegerInC d n largestInte
  • 按 Esc 按键关闭 Ajax Modal 弹出窗口

    我已经使用 Ajax 显示了一个面板弹出窗口 我要做的是当用户按 Esc 键时关闭该窗口 这可能吗 如果有人知道这一点或以前做过这一点 请帮助我 Thanks 通过以下链接 您可以通过按退出按钮轻松关闭窗口 http www codepro
  • 调用堆栈中的“外部代码”是什么意思?

    我在 Visual Studio 中调用一个方法 并尝试通过检查调用堆栈来调试它 其中一些行标记为 外部代码 这到底是什么意思 方法来自 dll已被处决 外部代码 意味着该dll没有可用的调试信息 你能做的就是在Call Stack窗口中单
  • 如何从 ODBC 连接获取可用表的列表?

    在 Excel 中 我可以转到 数据 gt 导入外部数据 gt 导入数据 然后选择要使用的数据源 然后在提供登录信息后 它会给我一个表格列表 我想知道如何使用 C 以编程方式获取该列表 您正在查询什么类型的数据源 SQL 服务器 使用权 看
  • 从列表中选择项目以求和

    我有一个包含数值的项目列表 我需要使用这些项目求和 我需要你的帮助来构建这样的算法 下面是一个用 C 编写的示例 描述了我的问题 int sum 21 List
  • 如何将 PostgreSql 与 EntityFramework 6.0.2 集成? [复制]

    这个问题在这里已经有答案了 我收到以下错误 实体框架提供程序类型的 实例 成员 Npgsql NpgsqlServices Npgsql 版本 2 0 14 2 文化 中性 PublicKeyToken 5d8b90d52f46fda7 没

随机推荐