在 C++ 草案标准中多次使用短语“强烈发生在之前”。
例如:终止 [basic.start.term]/5
如果具有静态存储持续时间的对象的初始化完成强烈发生在调用 std::atexit 之前(参见 [support.start.term]),则对函数的调用传递给 std::atexit在调用对象的析构函数之前排序。如果对 std::atexit 的调用强烈发生在具有静态存储持续时间的对象的初始化完成之前,则对对象的析构函数的调用在调用传递给 std::atexit 的函数之前排序. 如果对 std::atexit 的调用强烈发生在对 std::atexit 的另一次调用之前,则对传递给第二个 std::atexit 调用的函数的调用在传递给第一个 std::atexit 调用。
并在 数据竞赛 [intro.races]/12中定义
评估 A 强烈地发生在评估 D 之前,如果,
(12.1) A 在 D 之前排序,或
(12.2) A 与 D 同步,A 和 D 都是顺序一致的原子操作([atomics.order]),或
(12.3) 有评估 B 和 C 使得 A 在 B 之前排序,B 只是在 C 之前发生,C 在 D 之前排序,或者
(12.4) 有一个求值 B 使得 A 强烈地发生在 B 之前,而 B 强烈地发生在 D 之前。
[注:非正式地,如果 A 强烈地发生在 B 之前,那么在所有情况下 A 似乎在 B 之前被评估。强烈发生在排除消费操作之前。——尾注]
为什么要引入“之前发生的强烈事件”?直观地说,它与“发生在之前”有什么区别和关系?
注释中的“A 似乎在所有情况下都在 B 之前被评估”是什么意思?
(注意:这个问题的动机是 Peter Cordes 在这个答案下的评论。)
附加标准报价草案(感谢 Peter Cordes)
顺序和一致性 [atomics.order]/4
在所有 memory_order::seq_cst 操作(包括栅栏)上都有一个总顺序 S,它满足以下约束。首先,如果 A 和 B 是 memory_order::seq_cst 操作,并且 A 强烈地发生在 B 之前,那么 A 在 S 中先于 B。其次,对于对象 M 上的每一对原子操作 A 和 B,其中 A 是连贯有序的在B之前,S需要满足以下四个条件:
(4.1) 如果 A 和 B 都是 memory_order::seq_cst 操作,则 A 在 S 中先于 B;和
(4.2) 如果 A 是 memory_order::seq_cst 操作且 B 发生在 memory_order::seq_cst 围栏 Y 之前,则 A 在 S 中先于 Y;和
(4.3) 如果 memory_order::seq_cst 栅栏 X 发生在 A 之前且 B 是 memory_order::seq_cst 操作,则 X 在 S 中先于 B;和
(4.4) 如果 memory_order::seq_cst 栅栏 X 发生在 A 之前,B 发生在 memory_order::seq_cst 栅栏 Y 之前,则 X 在 S 中位于 Y 之前。