C++ 编译器优化如何影响代码逻辑?

C++ 编译器优化如何影响代码逻辑?,c++,c++11,g++,compiler-optimization,C++,C++11,G++,Compiler Optimization,当编译同一段代码时,完全禁用优化(g++-O0),然后再次完全启用优化(g++-O3),如何更改源代码本身的逻辑 例如,编译器可以 及 做 这两种优化使代码执行得更快,而不影响原始源代码的完整性。任何运行时没有这些优化的代码都将在启用这些优化的情况下运行 但是,编译器优化也会影响代码逻辑。以下是我知道的两个例子: 从临时措施中可以消除可能的副作用 重新排列包含浮点值的算术可能会影响浮点错误(希望需要-ffast math参数) 我很惊讶,也很幸运地了解到了这些,因为它们在错误的情况下可能

当编译同一段代码时,完全禁用优化(
g++-O0
),然后再次完全启用优化(
g++-O3
),如何更改源代码本身的逻辑

例如,编译器可以

这两种优化使代码执行得更快,而不影响原始源代码的完整性。任何运行时没有这些优化的代码都将在启用这些优化的情况下运行

但是,编译器优化也会影响代码逻辑。以下是我知道的两个例子:

  • 从临时措施中可以消除可能的副作用
  • 重新排列包含浮点值的算术可能会影响浮点错误(希望需要
    -ffast math
    参数)
我很惊讶,也很幸运地了解到了这些,因为它们在错误的情况下可能成为巨大的潜在陷阱

<>我想知道,C++编译器优化会影响代码逻辑吗?我特别想在g++编译器下查找有关c++11(没有任何未定义的行为)的信息,但欢迎为其他编译器提供提示。

假设规则:

一个实现可以自由地忽略本规范的任何要求 只要符合国际标准,结果就如同要求 已遵守,根据可观察到的情况确定 程序的行为。例如,实际的实现需要 如果表达式可以推断其值为 未使用,且无影响患者可观察行为的副作用 节目制作完成了

然而,该标准提到了一个允许的优化,它打破了“似乎”规则:

当满足某些条件时,允许省略实现 类对象的复制/移动构造,即使复制/移动 对象的构造函数和/或析构函数有副作用。In 在这种情况下,实现将处理 省略了复制/移动操作,仅作为两种不同的引用方式 对于同一对象,该对象的销毁发生在 后来这两个物体会被摧毁 没有优化。123这种省略复制/移动操作, 在下列情况下,允许复制省略 (可组合使用以消除多个副本):

-作为回报 当表达式 非易失性自动对象(函数除外)的名称 或catch子句参数),其类型与 函数返回类型,复制/移动操作可以通过 将自动对象直接构造到函数的返回中 价值观

-在抛出表达式中,当操作数是 非易失性自动对象(函数或catch子句除外 参数),其范围不超出最内层 封闭try块(如果有),从 异常对象(15.1)的操作数可以通过 将自动对象直接构造到异常对象中

- 当尚未绑定到引用的临时类对象 (12.2)将被复制/移动到具有相同 cv不合格类型,复制/移动操作可由 将临时对象直接构造到 省略复制/移动

-当异常的异常声明 handler(第15条)声明了一个相同类型的对象(除了 作为例外对象(15.1),复制/移动 通过将异常声明视为 异常对象的别名(如果程序的含义为 除了执行 由异常声明声明的对象

“未指定行为”是指实现可以自由选择任何可能行为的行为。在这种情况下,优化器可能会影响所做的选择

一个简单的例子是函数参数的求值顺序。非优化的构建可以使用从左到右或从右到左,而优化的构建可能以“混合”顺序计算参数。一个很好的理由是最大限度地利用参数之间的公共子表达式优化机会


如果这些参数中的任何一个有明显的副作用,那么代码逻辑就会改变,但这是否是一个bug会因情况而异。

不要忘记提到,未定义的行为将意味着一切。我相信编译器也可以“不计算”以后永远不会使用的东西。虽然这不会改变代码的逻辑,但如果您正在度量性能,那么这可能是不好的。不过我不确定。@leo说得好!尽管如此,我始终希望使用优化进行编译会执行得更快,因为这是优化器的工作。我认为更简洁地说,是您的问题:假设规则的所有例外情况是什么?@更神秘的是,未定义的行为意味着任何事情都会发生,甚至在程序中出现UB之前。