【问题标题】:Where in the C++ Standard is the memory layout of objects documented?C++ 标准在哪里记录了对象的内存布局?
【发布时间】:2018-11-21 00:38:58
【问题描述】:

这是一个大问题,所以我要求提供参考而不是小册子大小的答案。我正在阅读 Stroustrup 的 C++ 之旅,似乎对象的布局方式是内存是许多 C++ 功能设计的基础,例如POD 与聚合与具有虚拟成员的类。

不幸的是,Tour 本身并没有详细介绍这个主题,并且浏览一些标准参考资料(例如 C++ Primer 5ed 和 TCPPPL 4ed)的 ToC 并没有显示它们是否或在哪里涵盖它。

【问题讨论】:

标签: c++ language-lawyer memory-layout object-layout


【解决方案1】:

[class.mem]/18:

分配具有相同访问控制的(非联合)类的非静态数据成员,以便后面的成员在类对象中具有更高的地址。未指定具有不同访问控制的非静态数据成员的分配顺序。实现对齐要求可能会导致两个相邻的成员不能立即分配;管理虚拟功能和虚拟基类的空间需求也是如此。

[class.mem]/25:

如果标准布局类对象有任何非静态数据成员,则其地址与其第一个非静态数据成员的地址相同。否则,其地址与其第一个基类子对象(如果有)的地址相同。 [ 注意: 因此,标准布局结构对象中可能存在未命名的填充,但不是在其开头,这是实现适当对齐所必需的。 — 尾注 ] [ 注: 对象及其第一个子对象是指针可互转换的([basic.compound]、[expr.static.cast])。 — 尾注 ]

还有[dcl.array]表示数组在内存中是连续的,[class.bit]表示位域,[intro.object]表示对象大小和重叠子对象的概念。

可能还有其他地方。没有一个位置。

【讨论】:

  • 这是一个很好的参考,但我在其他地方找到了声明额外要求的语句,例如in cppreference 添加如下细节:“指向标准布局结构类型对象的指针可以是 reinterpret_cast指向它的第一个非静态数据成员(如果它有非静态数据成员)或它的第一个基类子对象(如果有的话)的指针,反之亦然。(在第一个数据成员之前不允许填充)。请注意,严格的别名规则仍然适用于此类转换的结果”。
  • 还有位域和数组。
  • @PasserBy 为我提供声明完整性的权利。
  • @DunPeal "can be reinterpret_cast" 1) 这是对表达式的保证,而不是对布局的保证。没有表达上的保证,版面的保证理论上是可以存在的。 2)实际上,当指针指向对象时,C++ 的分歧很大。 C++ 的一方面说必须正确派生指针,另一方面说包含正确地址的任何指针都指向恰好位于该地址的任何对象。所以有两种C++,一种是高级语义,另一种是低级语义。你需要说出你说的是哪一种。
猜你喜欢
  • 2014-03-07
  • 2010-12-10
  • 2022-01-09
  • 2021-08-11
  • 1970-01-01
  • 2012-07-03
  • 1970-01-01
  • 2020-03-06
  • 2020-08-08
相关资源
最近更新 更多