我何时以及为什么要使用 -fno-elide-constructors
When and why would I use -fno-elide-constructors?
我正在学习C++,我遇到了-fno-elide-constructors
,下面我包含了手册页的描述。
-fno-elide-constructors
The C++ standard allows an implementation to omit creating a
temporary which is only used to initialize another object of the
same type. Specifying this option disables that optimization, and
forces G++ to call the copy constructor in all cases.
因此,使用此选项,我可以禁用这种特定类型的编译器优化。我有一个程序,可以创建 2 个对象并将它们加在一起,并在使用库调用每个函数时打印BASIC4TRACE打印。我编译了同一个程序来测试函数调用的差异,同时使用此选项两次,一次有,一次没有,给出这个输出。
Without optimizations
BASIC4TRACE: (0x7fff7504a7c0)->Object(const char *)
BASIC4TRACE: (0x7fff7504a7d0)->Object(const char *)
BASIC4TRACE: (0x7fff7504a770)->Object(const char *)
BASIC4TRACE: op+(const Object&, const Object&)
BASIC4TRACE: (0x7fff7504a720)->Object()
BASIC4TRACE: (0x7fff7504a780)->Object(const Object&)
BASIC4TRACE: (0x7fff7504a720)->~Object()
BASIC4TRACE: op+(const Object&, const Object&)
BASIC4TRACE: (0x7fff7504a720)->Object()
BASIC4TRACE: (0x7fff7504a790)->Object(const Object&)
BASIC4TRACE: (0x7fff7504a720)->~Object()
BASIC4TRACE: (0x7fff7504a7f0)->Object(const Object&)
BASIC4TRACE: (0x7fff7504a790)->~Object()
BASIC4TRACE: (0x7fff7504a780)->~Object()
BASIC4TRACE: (0x7fff7504a770)->~Object()
BASIC4TRACE: (0x7fff7504a7e0)->Object(const Object&)
BASIC4TRACE: (0x7fff7504a7f0)->~Object()
BASIC4TRACE: (0x7fff7504a7e0)->~Object()
BASIC4TRACE: (0x7fff7504a7d0)->~Object()
BASIC4TRACE: (0x7fff7504a7c0)->~Object()
With optimizations
BASIC4TRACE: (0x7fffbfc8bbf0)->Object(const char *)
BASIC4TRACE: (0x7fffbfc8bc00)->Object(const char *)
BASIC4TRACE: (0x7fffbfc8bbb0)->Object(const char *)
BASIC4TRACE: op+(const Object&, const Object&)
BASIC4TRACE: (0x7fffbfc8bbc0)->Object()
BASIC4TRACE: op+(const Object&, const Object&)
BASIC4TRACE: (0x7fffbfc8bc10)->Object()
BASIC4TRACE: (0x7fffbfc8bbc0)->~Object()
BASIC4TRACE: (0x7fffbfc8bbb0)->~Object()
BASIC4TRACE: (0x7fffbfc8bc10)->~Object()
BASIC4TRACE: (0x7fffbfc8bc00)->~Object()
BASIC4TRACE: (0x7fffbfc8bbf0)->~Object()
如您所见,拨打的电话数量存在显着差异。所以我的问题是我什么时候会真正使用这个选项?是否存在这种类型的优化会导致问题的特定情况?我真的想不出我不希望我的代码尽可能优化的情况,所以我很难弄清楚这有什么好处。
正如 Benjamin Lindley 对这个问题的评论,如果你的程序依赖于复制构造函数的副作用,那么你的代码写得非常糟糕。应始终编写复制构造函数,以便此类优化是安全的。不仅因为编译器可以执行这样的优化,还因为其他人类读者将很难理解正在发生的事情。
也就是说,该选项仍然绝对有用。未指定何时省略复制构造函数,并且看似不相关的更改可能会更改是否发生复制省略。因此,-fno-elide-constructors
使GCC更具确定性,有时这有助于调试,因为这意味着您可以减少对仅通过添加调试打印语句即可开始工作的代码的担忧(作为副作用,恰好禁用了复制省略)。
您可能希望使用 -fno-elide-constructors
的另一个原因是,如果您希望您的代码在其他执行较少复制的编译器上表现良好。如果无用的复制构造函数导致明显的减速,您可以重新处理代码,以便无论是否省略副本,它都很快。
一个例子来自 rtti(实时类型信息)。如果您的程序使用 typeid() 函数,则它依赖于要实例化的类型。一个定义规则就是一个例子:
class mesh; // Forward (incomplete) declaration
if(property.type() == typeid(mesh*)) // Crash here in typeid()
{
// do something
}
现在想象一个稍微复杂的示例,其中 Your 类是模板化的:
template <class T0> class mesh { };
if(property.type() == typeid(mesh<T>*))
{
// do something
}
即使类是完全声明的,该类也可能永远不会被使用,因此永远不会被实例化。在这种情况下,避免段错误的唯一方法是禁用优化,这样类将始终被实例化,从而生成正确的 typeid。
通过编译 SymboliC++ 中的示例代码,可以找到一个真实示例。
- 为什么 boost::comb 对结构化绑定的支持缺少结构化绑定机制对 boost::tuples::cons 的适应?
- -fno-unwind-tables 和 -fno-async-unwind-tables 不起作用 NDK clang
- 为什么子项目 CMAKE 不考虑 fno-sanitize,请禁用目标的消毒器
- -fno-char8_t 的 MSVC 等效值是多少?
- Qt Creator 在执行步骤 "make" 时出现编译错误,-fno-stack-limit
- Qt creator语言 - fno-elide-constructors 不起作用
- "-fno-semantic-interposition"与"-fvisibility=p
- 不同类型的"decltype((const int)a)"和"decltype((cons
- call call cons构件功能的std ::元素的每个元素
- 使用 gcc 的 -fno-math-errno 可能有什么副作用?
- 在Macbook Pro上实现clang -fno-stack-protector编译代码时出现问题
- 为什么仅 -fno-signed-0 就可以实现优化,而似乎也需要 -ffinite-math-only (gcc)
- g++:如果在 -O2 或 -O3 之前指定,-fno-omit-frame-pointer 是否有效
- GCC 仍然使用 -fno-threadsafe-static 生成保护变量
- clang, std::function and -fno-rtti
- 即使使用-fno-elide-constructors编译,复制省略似乎也会发生
- -fno elide构造函数是否包含在-O0或任何其他优化级别中
- 当设置-fno-elide构造函数时,clang Xcode 4.4.1是否有错误
- 我何时以及为什么要使用 -fno-elide-constructors
- 带有-fno-elide-构造函数的临时对象