一般C&x2B+;性能改进提示 有人能指点我一篇文章,或者写一些关于C++编程习惯的建议,这些习惯通常是有效的(没有真正的缺点),并提高性能?我不是指编程模式和算法复杂性——我需要一些小东西,比如如何定义函数、在循环中要做/要避免的事情、在堆栈上分配什么、在堆上分配什么等等

一般C&x2B+;性能改进提示 有人能指点我一篇文章,或者写一些关于C++编程习惯的建议,这些习惯通常是有效的(没有真正的缺点),并提高性能?我不是指编程模式和算法复杂性——我需要一些小东西,比如如何定义函数、在循环中要做/要避免的事情、在堆栈上分配什么、在堆上分配什么等等,c++,C++,这不是让一个特定的软件更快,也不是如何创建一个干净的软件设计,而是编程习惯——如果你总是应用它们,你会让你的代码快一点而不是慢一点。一个好的起点是系列,还有那些从中成长出来的特殊C++书籍。 这是我过去提到的一个列表。除此之外,Google C++的性能提示也有相当大的价值。 中有许多提示,并且都是沿着这条线。 这类技巧的一个简单示例:尽可能使用预增量(++i)而不是后增量(i++)。这对于迭代器尤其重要,因为后增量涉及复制迭代器。您的优化器可能能够撤销此操作,但编写preincrement并不

这不是让一个特定的软件更快,也不是如何创建一个干净的软件设计,而是编程习惯——如果你总是应用它们,你会让你的代码快一点而不是慢一点。

一个好的起点是系列,还有那些从中成长出来的特殊C++书籍。

这是我过去提到的一个列表。除此之外,Google C++的性能提示也有相当大的价值。

中有许多提示,并且都是沿着这条线。


这类技巧的一个简单示例:尽可能使用预增量(++i)而不是后增量(i++)。这对于迭代器尤其重要,因为后增量涉及复制迭代器。您的优化器可能能够撤销此操作,但编写preincrement并不是额外的工作,所以为什么要冒险呢?

更喜欢使用preincrement

对于int/pointer等,没有区别。
但是对于类类型,标准的实现方式需要创建一个新对象

因此,我们更喜欢预增量。以防万一,以后会更改类型。

然后你就不需要修改代码来应付。

我养成了习惯,更喜欢编写
++I
而不是
I++
,这并不是说当
I
int
时它会带来任何性能提升,但是当
I
迭代器时情况就不同了,迭代器可能有一个复杂的实现

那么假设你来自C编程语言,放弃在函数开始时声明所有变量的习惯:在函数流中需要变量时声明变量,因为函数可能包含早期的
return
语句,然后才有效地使用开始时初始化的一些变量

除此之外,另一个资源是赫伯·萨特(又是他)和亚历克赛·亚历山德雷斯库

还有Scott Meyers的高效C++的最新版本:


最后,我想提及Tony Albrecht的演讲:不是说它包含了你可以盲目遵循的经验法则,而是它是一本非常有趣的读物。

如果我理解正确,你问的是关于避免过早悲观的问题,这是避免过早优化的一个很好的补充。根据我的经验,要避免的第一件事是尽可能不复制大型对象。这包括:

  • 通过(常量)引用将对象传递给函数
  • 只要可行,就通过(常量)引用返回对象
  • 确保在需要时声明引用变量
最后这一点需要一些解释。我不能告诉你我已经看过多少次了:

class Foo
{
    const BigObject & bar();
};

// ... somewhere in code ...
BigObject obj = foo.bar();  // OOPS!  This creates a copy!
正确的方法是:

const BigOject &obj = foo.bar();  // does not create a copy

这些准则适用于比智能指针或内置类型更大的任何对象。另外,我强烈建议您花时间学习评测代码。一个好的分析工具将有助于捕获浪费的操作。

我建议阅读Jon Bentley的第二章(“性能”)。它不是C++特定的,但是这些技术也可以应用在C或C++中。该网站仅包含本书的部分内容,我建议您阅读本书。

尽可能避免对同一数据集进行多次迭代。

对于优化技术来说,“”by通常是最好的参考之一,既简单,也肯定更高级。另一个巨大的优势是,可以在他的网站上免费阅读。(他的网站请参见他名字中的链接,pdf文件请参见文章标题中的链接)

编辑:还要记住,90%(或更多)的时间花费在10%(或更少)的代码中。所以,一般来说,优化代码实际上就是要找出瓶颈。更重要的是,现代编译器的优化效果要比大多数编码器好得多,尤其是微优化,如延迟变量初始化等。编译器通常非常擅长优化,因此要花时间编写稳定、可靠和简单的代码


我认为,至少在大多数情况下,更多地关注算法的选择而不是微观优化是值得的。

这是一篇关于这个主题的好文章:

使用函子(实现了
操作符()
的类)而不是函数指针。编译器可以更轻松地内联前者。这就是为什么C++的
std::sort
比C的
qsort

性能更好的原因。提高这些技能的最佳方法是阅读书籍和文章,但我可以为您提供一些技巧:

  • 1-按引用接受对象,按值接受原语或指针类型,但如果函数存储指向对象的引用或指针,则使用对象指针
  • 2-不要使用宏声明常量->使用静态常量
  • 3-如果您的类可能是子类,请始终实现虚拟析构函数
      • 避免多重继承
      • 在必要时使用虚拟现实,而不仅仅是为了好玩
      • 仅当不想使用模板化集合类时才使用模板化集合类

        • 模板!使用模板可以减少代码量,因为您可以拥有一个可以与许多数据类型重用的类或函数/方法

          考虑以下几点:

          #include <string>
          using std::basic_string;
          
          template <class T>
              void CreateString(basic_string<T> s)
              {
                  //...
              }
          
          #包括
          使用std::basic_字符串;
          模板
          void CreateString(基本字符串)
          {
          //...
          }
          
          基本字符可以由char、wchar、unsigned char或u组成
          // this is a better option
          void some_function(const std::string &str);
          // than this:
          void some_function(std::string str);
          
          // Not a good idea, a whole other temporary copy of the (potentially big) vector will be created.
          int sum(std::vector<int> v)
          {
             // sum all values of v
             return sum;
          }
          
          // Better, vector is passed by constant reference
          int sum(const std::vector<int>& v)
          {
             // v is immutable ("read-only") in this context
             // sum all values of v.
             return sum;
          }