什么时候以及为什么要使用-fno-elide-constructors? [英] When and why would I use -fno-elide-constructors?

查看:107
本文介绍了什么时候以及为什么要使用-fno-elide-constructors?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习C ++,遇到了 -fno-elide-constructors ,下面我在手册页中进行了介绍。

I'm learning C++ and I came across the -fno-elide-constructors, below I have included the description from the man page.

   -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库调用每个函数时进行打印。我编译了相同的程序,以测试两次使用此选项时的函数调用的差异,一个带有一个,另一个不带有这个输出。

So with this option I am able disable this particular type of compiler optimization. I have a program that creates 2 objects and adds them together and prints when each of the function is called using using BASIC4TRACE library. I compiled the same program to test the difference in function calls while using this option twice, one with and one without, giving this output.

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()

如您所见,拨打的电话数量有很大的不同。所以我的问题是,我何时会真正使用此选项?是否存在这种优化导致问题的特定情况?我真的无法想到我不希望我的代码得到尽可能优化的情况,因此我很难尝试找出这样做的好处。

As you can see there is a significant difference in the number of calls made. So my question is when would I actually use this option? Is there a specific case where this type of optimization causes problems? I can't really think of a situation where I wouldn't want my code to be optimized as much as possible so I am having a hard time trying to figure out what this is good for.

推荐答案

正如本杰明·林德利(Benjamin Lindley)对这个问题的评论一样,如果您的程序依赖于复制构造函数的副作用,那么您的代码将非常糟糕书面。应该始终编写您的副本构造函数,以便这种优化是安全的。不仅因为编译器可能会进行这种优化,还因为其他人类读者否则很难理解正在发生的事情。

As Benjamin Lindley commented on the question, if your program relies on the side effects of copy constructors, your code is very badly written. Your copy constructors should always be written so that such optimisations are safe. Not only because the compiler may perform such optimisations, also because other human readers will otherwise have a very hard time understanding what is going on.

也就是说,该选项仍然可以绝对有用。确切地说,何时删除复制构造函数是不确定的,看似不相关的更改可能会更改复制省略是否发生。因此, -fno-elide-constructors 使GCC更具确定性,有时这有助于调试,因为这意味着您不必担心仅通过添加调试即可开始工作的代码打印语句(其副作用是禁用复制清除)。

That said, the option can still definitely be useful. Exactly when copy constructors are elided is unspecified, and seemingly irrelevant changes may change whether copy elision happens. Thus, -fno-elide-constructors makes GCC more deterministic, and sometimes, that helps in debugging, as it means you can worry less about code that starts working just by adding debug print statements (which as a side effect happen to disable copy elision).

您可能想使用 -fno-elide-constructors <的另一个原因是如果您希望代码在执行较少复制省略的其他编译器上良好执行。如果无用的副本构造函数导致明显的速度下降,则可以重新编写代码,以便无论是否删除副本都可以快速执行代码。

Another reason you may want to use -fno-elide-constructors is if you want your code to perform well on other compilers that perform less copy elision. If the useless copy constructors cause a noticeable slowdown, you can re-work the code so that it's fast regardless of whether copies get elided.

这篇关于什么时候以及为什么要使用-fno-elide-constructors?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆