现代的c ++编译器会优化不可变的临时变量吗?

时间:2018-08-02 15:38:08

标签: c++ gcc optimization

例如,我有这样的代码:

void func(const QString& str) 
{
    QString s = str.replace(QRegexp("[abc]+"), " ");
    ......
 }

编译器是否会优化var QRegep(“ [abc] +”),仅构造一次即可,而不是每次调用 func 时都要构造?或者换句话说,我是否需要重新实现编码以提高性能,例如:

void func(const QString& str) 
{
    static const QRegexp sc_re("[abc]+");
    QString s = str.replace(sc_re, " ");
    ......
 }

将QRegexp设置为静态const变量。

1 个答案:

答案 0 :(得分:0)

  

编译器会优化var QRegep(“ [abc] +”),仅构造一次而不是每次调用 func 构造一次吗?

您假设对func的每次调用都将构造一个相同的QRegexp对象,但是您怎么知道呢?例如,您怎么知道这些对象不包含序列号(一个整数成员,该序列号设置为先前构造的QRegexp个对象的数目)?如果使用了这样的序列号,则编译器只构造一次临时变量是错误的。

好的,我们可以合理地猜测没有发生这样的事情。但是,关键是我们在猜测,并且不允许编译器猜测。因此,编译器考虑这种优化的前提条件是可以使用构造函数的定义(这是该类的实现细节,您不应依赖于此)。

如果可以使用构造函数的定义,并且在给定相同输入的情况下该定义可证明产生相同的结果(以及可能使我暂时忽略的其他技术限制),则可以使用编译器进行优化。

我不知道是否有编译器选择在允许同时有益(您所做的另一种假设)时提供这种优化。在启用和未启用优化的情况下,对这两个候选程序的性能测试应该可以揭示您的特定编译器是否可能会利用这一优势。

  

换句话说,我是否需要重新实现编码,以提高性能:

您几乎根本不需要重新实现性能。 (一个例外是,如果您的代码效率太低,则需要几个世纪才能完成。我很确定我们不在此范围之内。)一个更好的问题是“应该”。我会去的。

在这种特定情况下,我会猜测“不,这看起来像是过早的优化”。但是,这只是一个猜测,因此,我将继续遵循您可以应用的一般准则。

仅在以下情况下才应重新实施性能: 1)最终用户可以明显看到性能提升,或者 2)新代码使程序员更易于阅读和理解。 在其他情况下,请依靠编译器进行适当的优化。

在您的情况下,我看到了变量名sc_re,并认为“那是什么?” 所以第二点就出来了。这留下了明显的性能提升的问题。通常,这不是通过简单地询问就能确定的。通常,它涉及性能测试,可能至少涉及两种类型。一项测试将对两个候选对象进行人工繁重的计时,以查看性能提升有多大(如果有的话)。另一个测试将分析您的实际程序,以查看是否经常调用此代码以使最终用户注意到该增益。一个好的第三项测试是将实际程序提供给最终用户,看看他们是否注意到差异。

在这些测试中,剖析可能是您时间上最有生产力的使用。 (众所周知,程序员在没有探查器的帮助下就无法确定真正的性能障碍。)如果您每5分钟在此功能上花费2毫秒,为什么还要花时间尝试改善它呢?另一方面,如果每次调用此函数都花费1秒钟,则探查器可能会告诉您此构造函数是否是罪魁祸首。