我正在学习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
的另一个原因是,如果您希望代码在其他执行较少复制省略的编译器上表现良好。如果无用的拷贝构造函数导致速度明显下降,则可以重新编写代码,以便无论是否删除拷贝都可以快速执行代码。