在完全禁用(g++ -O0
)优化的情况下编译同一段代码,然后再次完全启用优化(g++ -O3
)时,如何更改源代码本身的逻辑?
例如,编译器可以
这两个优化使代码执行速度更快,而不会影响原始源代码的完整性。在没有这些优化的情况下运行的任何代码都将在启用它们的情况下运行。
但是,编译器优化也会影响代码逻辑。以下是我所知道的两个例子:
-ffast-math
参数)。我很惊讶,很幸运,要了解这些因为他们可能在错误的情况下成为巨大的潜在陷阱。
所以我想知道,有没有其他情况下c ++编译器优化会影响代码逻辑?我特意在g ++编译器下查找有关c ++ 11(没有任何未定义的行为)的信息,但欢迎提供其他编译器的提示。
答案 0 :(得分:8)
“as-if”规则:
实施可以自由忽略对此的任何要求 国际标准只要结果就好像要求一样 已经遵守,只要可以从观察中确定 该计划的行为。例如,实际的实施需要 如果它可以推导出它的值,则不评估表达式的一部分 未使用,没有影响可观察行为的副作用 制作该节目。
但是,标准提到了一个允许的优化,它打破了“假设”规则:
当满足某些条件时,允许省略实现 复制/移动类对象的构造,即使复制/移动 对象的构造函数和/或析构函数有副作用。 在这种情况下,实施处理的来源和目标 省略了复制/移动操作,只是两种不同的引用方式 对于同一个对象,该对象的破坏发生在 稍后两个物体被摧毁的时间 没有优化.123这种复制/移动操作的省略, 在下列情况下允许使用复制省略 (可以合并以消除多个副本):
- 回报 表达式中带有类返回类型的函数中的语句 是非易失性自动对象的名称(函数除外) 或者catch-clause参数)与cvunqualified类型相同 函数返回类型,可以省略复制/移动操作 将自动对象直接构造到函数的返回中 价值
- 在throw-expression中,当操作数是a的名称时 非易失性自动对象(函数或catch子句除外) 参数)其范围不超出最内层的末端 封闭try-block(如果有的话),复制/移动操作 异常对象(15.1)的操作数可以省略 将自动对象直接构造到异常对象
- 当一个尚未绑定到引用的临时类对象时 (12.2)将被复制/移动到具有相同的类对象 cv-unqualified类型,可以省略复制/移动操作 将临时对象直接构造到目标中 省略了复制/移动
- 异常声明时的异常 handler(第15条)声明了一个相同类型的对象(除了 cv-qualification)作为异常对象(15.1),复制/移动 通过将异常声明视为一个来省略操作 如果程序的含义是异常对象的别名 除了执行构造函数和析构函数之外没有变化 异常声明声明的对象。
答案 1 :(得分:1)
“未指定的行为”是指实现可以自由选择任何可能行为的行为。在这种情况下,优化程序可能会影响所做的选择。
一个简单的例子是评估函数参数的顺序。非优化构建可以使用从左到右或从右到左,而优化构建可以以“混合”顺序评估参数。一个很好的理由是在参数中最大化共同表达式优化的机会。
如果这些参数中的任何一个有明显的副作用,代码逻辑会被改变,但是这个错误是否因情况而异。