C++如同规则

如同规则就是允许进行任何不改变程序可观察行为

解释

只要保证以下几点,就允许 C++ 编译器对程序进行任何修改:

1) 在每一个序列点, 所有 volatile 对象的值是稳定的(之前的求值已经完成,新的求值没有开始)

(C++11 前)

1) 对 volatile 对象的访问(读或写)严格按照它们所发生的表达式的语义进行。特别地,它们和同一线程中的其他 volatile 访问之间不会发生重排

(C++11 起)

2) 程序终止时,写入文件的数据完全如同程序是按照所写的代码那样执行的一般。

3) 发送到交互式设备的提示文本将在程序等待输入之前显示出来。

4) 如果 ISO C 编译指示 #pragma STDC FENV_ACCESS 受到支持并被设为 ON,则保证浮点算术运算符和函数调用会观察到对浮点环境(浮点异常和舍入模式)的修改,就如同按照所写的代码那样执行一般,除非

  • 除去转型和赋值以外的任何浮点表达式的结果可能有不同于表达式本身的浮点范围和精度(参见 FLT_EVAL_METHOD )
  • 尽管如此,任何浮点表达式的中间结果可能按照无限的范围和精度进行计算(除非 #pragma STDC FP_CONTRACT 为 OFF )

注释

由于编译器(通常)不能分析一个外部库的代码,以确定它是否执行 I/O 或者 volatile 访问,因此第三方库的调用同样不受这种优化的影响。然而,标准库调用可能会在优化过程中被其它调用替换,被消除,或者被添加到程序中。静态连接的第三方库代码可能会参与连接时优化。

未定义行为的程序,例如,越界的数组访问,修改 const 对象,违反求值顺序的规定等,不受“如同”规则的限制:当使用不同的优化设置重新编译时,它们常常会表现出不同的可观察行为。例如,如果一个有符号整数溢出的测试依赖于溢出的结果,比如 if(n+1 < n) abort(); ,则它会被某些编译器完全删除,因为有符号数溢出是未定义行为而优化器可以自由地假设它永远不会发生,从而测试是多余的。

复制消除是“如同”规则的一项例外:编译器可以删除对移动和复制构造函数的调用以及关联的临时对象的析构函数的调用,纵使这些调用具有可观察的副作用也是如此。 (C++17以后返回值优化是强制要求的,而不再被当做复制消除;)

new 表达式拥有“如同”规则的另一项例外:编译器可以删除对可替换分配函数的调用,即使提供了一个用户定义的替代函数并且具有可观察的副作用也是如此。

(C++14 起)

浮点异常的数目和顺序可以被优化改变,只要下一次浮点操作所观察到的状态就如同没有优化发生一样即可

如同规则 - cppreference.comhttps://zh.cppreference.com/w/cpp/language/as_if

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值