【问题标题】:Does placement-new introduce a sequence point?Placement-new 是否引入了序列点?
【发布时间】:2011-06-27 17:56:49
【问题描述】:

考虑以下代码行:

new (p++) T();

如果构造函数T()抛出异常,是否保证p已经自增?

【问题讨论】:

  • 这是一个很好的问题,但我希望你永远不会写出这样的代码 :-)
  • @sel:确实,我用new (p) T(); ++p; 替换了它,因为它更容易理解并且不同的语义(no 在抛出异常时递增)更适合我的程序逻辑.

标签: c++ exception constructor side-effects sequence-points


【解决方案1】:

来自 5.3.4 [expr.new](引自 n3242):

11 new-placement 语法用于 提供额外的论据 分配函数。如果使用,过载 对函数执行解析 通过组装参数创建的调用 由空间量组成的列表 请求(第一个参数)和 new-placement 部分中的表达式 新表达式(第二个和 后续参数)。

所以在一个新的表达式中,分配函数是从函数调用中使用的(这是有道理的)。所有分配函数都是函数,包括实现提供的函数,来自 3.7.4.1 [basic.stc.dynamic.allocation]:

1 分配函数应该是类成员函数或全局函数; [...]

所以当构造函数抛出异常时,分配已经发生并且相关的函数调用表达式已经被完全评估。

【讨论】:

    【解决方案2】:

    是的,它保证会增加。

    运算符只是函数/方法调用的语法糖。
    我不相信 new 在操作符之上有任何特殊含义,所以应该是一样的。

    因此,在调用函数 new 之前,所有参数都被完全评估(带有序列点)。

    【讨论】:

      【解决方案3】:

      我不认为标准直接/明确地回答了这个问题。然而,隐含的答案是肯定的。

      特别是,new 的放置语法只是一种指定将传递给函数的额外参数的方法。与任何其他函数调用一样,在评估函数的所有参数(以未指定的顺序)和执行函数中的任何代码之间存在一个序列点。我相信这应该意味着您的p++ 将被评估并在其他任何事情发生之前应用所有副作用。

      【讨论】:

        【解决方案4】:

        Placement new 只是一个常规函数,名为operator new(size_t, void*)。它只是返回它的第二个参数。

        【讨论】:

        • 您将placement-new 与operator new 混淆了。
        • 不这么认为。好吧,准确地说,placement-new 是调用 operator-new 的重载形式的语法,但普通的 oeople 也只是将这些形式称为placement-new。
        • Placement new 和 operator new 是正交概念。非常正交的概念。如果您使用placement new,则没有调用operator new。
        【解决方案5】:

        增量运算符执行以下操作:

        1. 将旧值存储在内部副本中
        2. 以 1 递增
        3. 返回旧值
        4. 删除旧值的副本

        所以,p 保证会递增。

        【讨论】:

        • 不要那么肯定。比如看这个问题:stackoverflow.com/questions/6482035/…
        • 增量不能保证在下一个序列点之前可见,这就是我的问题。
        • 好的@FredOverflow,错过了答案中的主题,sry @Fred Larson,你是对的,我应该告诉:这只是标准定义。如果编译器不这样做,那就是另外一回事了。
        猜你喜欢
        • 2021-08-22
        • 2012-10-15
        • 2014-06-15
        • 2021-08-31
        • 2023-03-22
        • 1970-01-01
        • 2016-06-25
        • 1970-01-01
        • 2010-09-26
        相关资源
        最近更新 更多