为什么-O0不能禁用gcc的编译优化?

5
string str="fujian";

一些书籍称代码会触发复制构造函数,但g++会进行优化,使得不会调用复制构造函数。

然而,我使用了g++命令-O0来禁用优化,但仍无法触发复制构造函数。

如何理解这个问题?


你是如何确定复制构造函数是否被调用的? - Joseph Mansfield
我重写了拷贝构造函数并记录了调用。 - jiafu
我的猜测是在某个地方,g++正在进行常量折叠/传播 - 可能是在前端。而且我猜你不能禁用它。 - JohnTortugo
如果你不想让复制构造函数被考虑,只需使用“直接初始化” string str("fujian") - Joseph Mansfield
请参见 https://en.wikipedia.org/wiki/Copy_elision 的最后一段:"GCC 提供了 -fno-elide-constructors 选项来禁用复制省略。该选项对于观察(或不观察!)返回值优化或其他省略复制的优化效果非常有用。通常不建议禁用此重要的优化。" - Jonathan Wakely
2个回答

9

使用GCC和Clang编译器,你可以使用 -fno-elide-constructors 编译标志来关闭复制/移动省略优化。


我不想把所有东西都复制,而是要理解基本原则以便学习。 - jiafu
@jiafu:我不确定为什么-o0不能帮助抑制复制/移动省略。如果你想要抑制这种行为,你需要使用该标志。 - Andy Prowl
8
这是一种特殊类型的优化,允许修改程序的行为(不遵循“as-if”规则)。因此关闭它可能会实际修改程序的行为,这是不好的。使用 -o 切换优化级别不应该改变程序的行为。@jiafu - juanchopanza
@juanchopanza:非常好的见解,那很可能是理由。 - Andy Prowl
2
只是澄清一下:优化选项是 -O 而不是 -o - rubenvb
@juanchopanza,你的回答还有更多的文章吗?我仍然无法做出自信的决定来了解它们之间的区别。谢谢。 - jiafu

1
复制省略规则基于ISO C++ 12.8。虽然其他用于优化的规则通常被称为“as-if”规则,这些规则在第1条中允许实现生成程序的行为与基于抽象机器模型的“非优化”程序语义有所不同,但是这个规则非常特殊,以至于您可以将“优化”代码本身视为与原始含义完全相同。换句话说,在抽象机器的行为中可能根本不存在省略的构造函数调用。
如果没有未定义的行为,则按照as-if规则进行优化或不进行优化,优化程序和非优化程序的可观察行为应该相同(尽管它们在性能等方面可能有所不同)。但是,复制省略更加激进,即它可以改变可观察行为。
最好不要依赖复制省略产生的差异。因此,保持普通优化选项的相同行为并为那些了解风险并确实需要的用户提供控制精确(不同)行为的单独选项是合理的。
WG21 / N4296 1.9 程序执行 5 符合规范的实现在执行一个格式良好的程序时,应该产生与相应的抽象机器实例以相同的程序和输入执行所可能产生的行为相同的可观察行为。然而,如果任何这样的执行包含未定义的操作,则本国际标准不对执行该程序及其输入的实现(甚至是在第一个未定义操作之前的操作)施加任何要求。
8 符合规范的实现的最低要求是:
(8.1) - 对易失性对象的访问严格按照抽象机器的规则进行评估。
(8.2) - 在程序终止时,所有写入文件的数据都必须与根据抽象语义执行该程序将产生的可能结果之一相同。
(8.3) - 交互设备的输入和输出动态应以这样的方式进行,即在程序等待输入之前实际传递提示输出。什么构成交互设备是由实现定义的。
这些统称为程序的可观察行为。[注意:每个实现可以定义抽象和实际语义之间更严格的对应关系。-注] 12.8 复制和移动类对象 31 当满足某些条件时,实现允许省略类对象的复制/移动构造,即使为复制/移动操作选择的构造函数和/或对象的析构函数具有副作用。在这种情况下,实现将省略的复制/移动操作的源和目标视为仅是引用同一对象的两种不同方式,并且该对象的销毁发生在两个对象将在没有优化的情况下被销毁的时间中较晚的时间点。这种称为复制省略的复制/移动操作可以在以下情况下允许(可以组合以消除多个副本):

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接