为什么 -O0 不能禁用 gcc 编译优化?
Why can't -O0 disable gcc compile optimization?
string str="fujian";
有些书说代码会触发复制构造函数,但g++会对其进行优化,使复制构造函数不会被调用。
然而,我使用g++命令- 0来禁用优化,但它仍然不能触发复制构造函数。
如何理解?
对于GCC和Clang,您可以使用-fno-elide-constructors
编译标志来关闭复制/移动省略优化。
复制省略规则基于ISO c++ 12.8。虽然通常用于优化的其他规则在第1条中统称为"as-if"规则(它允许实现生成的程序的行为与基于抽象机器模型的"非优化"程序语义有所不同),但此规则非常特殊,您可以将"优化"代码本身的行为与原始含义一样精确。换句话说,省略的构造函数调用可能根本不存在于抽象机器的行为中。
如果没有未定义行为,无论是否根据as-if规则进行优化,优化后的程序和未优化的程序的可观察行为应该是相同的(尽管它们可能在性能等方面有所不同)。然而,复制省略更具侵略性,也就是说,它可以改变可观察的行为。
你最好不要依赖于复制省略产生的差异。因此,对于普通的优化选项保持相同的行为,并为了解风险并且确实需要的用户提供单独的选项来控制精确(不同)的行为是合理的。
WG21/N4296
1.9程序执行 一个执行格式良好的程序的一致性实现应该产生相同的可观察到的行为作为抽象机的对应实例用同一程序执行的一种可能同样的输入。但是,如果任何此类执行包含未定义的操作,则本国际标准对使用该输入执行该程序的实现没有要求(甚至没有)(关于第一个未定义操作之前的操作)一个符合要求的实现的最低要求是:
(8.1) -对易失性对象的访问严格按照抽象机的规则求值。
(8.2)—在程序终止时,写入文件的所有数据应与下列任一可能结果相同根据抽象语义执行程序将产生。
(8.3)—交互设备的输入和输出动态应以如下方式进行输出实际上是在程序等待输入之前交付的。什么是互动设备是由实现定义的。
这些统称为程序的可观察行为。[注:更严格的通信抽象语义和实际语义之间可以由每个实现定义。-end note]12.8复制和移动类对象
31当满足某些条件时,允许实现省略类的复制/移动构造对象,即使为复制/移动操作选择了构造函数和/或对象的析构函数有副作用。在这种情况下,实现处理省略的复制/移动的源和目标操作就是引用同一对象的两种不同方式,以及该对象的销毁发生在时间的后期,如果没有优化,两个对象就会被破坏这种复制/移动操作的省略,称为复制省略,在以下情况下是允许的(其中可以组合以消除多个副本):
…
- 如果所有派生类在编译时都是已知的,那么final关键字是否提供了优化
- 向 cppFlags 添加"-O0"无法禁用 Android Studio 中的 clang 编译优化
- 当编译时已知引用占用结构中的空间时,是否错过了优化?
- 使用 -O1 优化标志编译项目时共享库崩溃
- 应用于整型类型的编译时优化 'std::isfinite()'
- 未经GCC优化而编译的简单C++程序不会产生预期的结果
- 使用优化标志进行编译时线程不启动
- 对 constexpr 与内联函数的调用编译为不同的程序集,并禁用优化
- 使用优化编译时的多线程程序块
- 编译时循环优化
- 在VS2017中编译错误C2027,但没有小对象优化
- 挥发性是否充当优化的编译屏障
- 编译时,复制构造函数/复制分配和正常功能调用优化之间是否存在任何区别
- GCC可以优化具有编译时常量变量的类的方法吗
- 通过宏定义编译标志(C++11 和优化)
- Visual Studio仍然可以优化预编译的代码
- 是否可以将addr2line与使用发布优化参数编译的应用程序一起使用
- C++强制对变量引用进行编译优化,使之成为直接的
- 从可执行文件中查找编译优化标志
- 为什么 -O0 不能禁用 gcc 编译优化?