什么时候在 C++ 中使用 [[no_unique_address]] 是安全的?

问题描述 投票:0回答:1

我明白

[[no_unique_address]]
的用途(这个答案很有帮助),但是我如何判断它是否可以安全使用?

我正在寻找一组足以知道用

[[no_unique_address]]
标记班级成员是安全的条件。例如,“如果类不将成员的地址与任何内容进行比较,那么它总是安全的”(假设这是真的)。理想情况下,答案也会引用该标准来证明为什么其条件是充分的。

c++ attributes language-lawyer c++20
1个回答
0
投票

根据 [dcl.attr.nouniqueaddr][intro.object]/7

[[no_­unique_­address]]
对结构成员的影响是使该成员成为 潜在重叠子对象。因此,我们可以从该术语倒推,找到标准对这些领域的规定。以下是 N4868 中提到的所有内容:

  • [intro.object]/8:成为潜在重叠的子对象是对象大小为零的必要条件,从而排除空基类。

    这是

    [[no_unique_address]]
    的基本原因,正如问题链接的“什么是
    [[no_unique_address]]
    ”答案中所讨论的。我们可以找到涉及零/非零大小对象的更多引用:

    • [intro.object]/9 意味着不同类型的零大小子对象可能具有相同的地址。 (可以说,它还说它们可能占用相同的存储字节,但大概不存在这样的字节。)

    • [intro.object]/9 还保证零大小的子对象的地址将是子对象所属的完整对象所占用的某个字节的存储地址。

    • [expr.rel]/4.2 保证仅对于非零大小的对象,指向包含对象内的子对象的指针的顺序。

    • [class.prop]/3.7.2 对类型是否是标准布局类施加了条件。老实说,我并不完全理解这里的措辞,但很明显,只有当考虑类型具有基类时,这才是相关的。

      (似乎缺少一个量词。可以有多个零大小的非静态数据成员,对吧?)

    • [meta.unary.prop]/4 表示即使

      std::is_empty<S>
      具有非静态数据成员,只要它们的大小为零,
      S
      也可以为 true。

    • [istream.unformatted]/1 仅当字符数组具有非零大小时,才为未格式化的输入函数提供与空字节相关的保证。

  • [basic.life]/8 表示如果一个对象是潜在重叠的子对象,则该对象不能被另一个对象“透明地替换”。这意味着您无法销毁并重新创建可能重叠的子对象并期望现有的指针/引用/名称能够工作。

  • [basic.types.general]/2

    表示您无法将可能重叠的子对象的存储复制为字节,然后放回原位并期望它具有相同的值。

  • [basic.types.general]/3

    表示您无法将一个对象的存储作为字节复制到另一个对象的存储上,并且如果其中一个对象是潜在的,则期望第二个对象与第一个对象具有相同的值-重叠子对象。

  • expr.sizeof

    表示类型 sizeof(S)

    S
    可能大于
    S
    类型的潜在重叠子对象的大小。同样,我认为,当应用于子对象本身而不是其类型时。
    
    

  • 所以,在像英语这样的语言中,
以下条件就足够了

您不介意对象的地址与另一个对象的地址别名。 (这似乎只发生在不同类型的对象上。)
  • 您不需要保证涉及成员的指针的排序。
  • 你不关心以字段类型为基类的包含对象是否是标准布局。
  • 根据
  • std::is_empty
  • ,你不介意包含对象是否为空。
    您不会将该字段交给 istream 输入函数。
  • 您不会玩带有对象生命周期的游戏并期望指针/引用/名称继续工作。
  • 您不会在涉及字符数组的字段上进行类型双关。
  • 您不介意
  • sizeof
  • 为会员提供太大的答案。
    
        
© www.soinside.com 2019 - 2024. All rights reserved.