string str="fujian";
有的书说代码会触发拷贝构造函数,但是g++会优化它,让拷贝构造函数不会被调用。
但是,我使用 g++ 命令 -O0 禁用了优化,但它仍然无法触发复制构造函数。
怎么理解?
使用 GCC 和 Clang,您可以使用-fno-elide-constructors
编译标志来关闭复制/移动省略优化。
复制省略规则基于 ISO C++ 12.8。虽然通常用于优化的其他规则在第 1 节中统称为“as-if”规则(它允许实现生成程序的行为与基于抽象机器模型的“非优化”程序语义有所不同),但该规则是如此特别是您可以将“优化”代码本身的行为与原始含义一样精确。换句话说,省略的构造函数调用可能根本不存在于抽象机器的行为中。
如果没有未定义的行为,无论是否根据 as-if 规则进行优化,优化程序和非优化程序的可观察行为应该是相同的(尽管它们可能在性能等方面有所不同)。然而,复制省略更具侵略性,即它可以改变可观察的行为。
您最好不要依赖复制省略产生的差异。因此,对普通优化选项保持相同的行为并为熟悉风险并确实需要它的用户提供单独的选项来控制精确(不同)行为是合理的。
WG21/N4296
1.9 程序执行
5 执行格式良好的程序的一致实现应产生与具有相同程序和相同输入的抽象机的相应实例的可能执行之一相同的可观察行为。但是,如果任何此类执行包含未定义的操作,则本国际标准对使用该输入执行该程序的实现没有要求(甚至不考虑第一个未定义操作之前的操作)。
8 对一致性实施的最低要求是:
(8.1) — 对 volatile 对象的访问严格按照抽象机的规则进行评估。
(8.2) — 在程序终止时,写入文件的所有数据应与根据抽象语义执行程序可能产生的结果之一相同。
(8.3) — 交互式设备的输入和输出动态应该以这样一种方式发生,即在程序等待输入之前实际交付提示输出。构成交互式设备的内容是实现定义的。
这些统称为程序的可观察行为。[注:抽象和实际语义之间更严格的对应关系可以由每个实现来定义。——尾注]
12.8 复制和移动类对象
31 当满足某些条件时,允许实现省略类对象的复制/移动构造,即使为复制/移动操作选择的构造函数和/或对象的析构函数有副作用。在这种情况下,实现将省略的复制/移动操作的源和目标简单地视为引用同一对象的两种不同方式,并且该对象的销毁发生在两个对象本应被删除的较晚时间。在没有优化的情况下销毁。122 这种复制/移动操作的省略,称为复制省略,在以下情况下是允许的(可以结合起来消除多个副本):
...