C++构造函数性能

标签 c++

在 C++17 中,如果我们设计这样一个类:

class Editor {
public:
  // "copy" constructor
  Editor(const std::string& text) : _text {text} {}

  // "move" constructor
  Editor(std::string&& text) : _text {std::move(text)} {}

private:
  std::string _text;
}

看起来(至少对我而言)“移动”构造函数应该比“复制”构造函数快得多。

但是如果我们尝试测量实际时间,我们会看到一些不同的东西:

  int current_time()
  {
    return chrono::high_resolution_clock::now().time_since_epoch().count();
  }

 int main()
 {
   int N = 100000;

   auto t0 = current_time();
   for (int i = 0; i < N; i++) {
     std::string a("abcdefgh"s);
     Editor {a}; // copy!
   }
   auto t1 = current_time();
   for (int i = 0; i < N; i++) {
     Editor {"abcdefgh"s};
   }
   auto t2 = current_time();

   cout << "Copy: " << t1 - t0 << endl;
   cout << "Move: " << t2 - t1 << endl;
 }

复制和移动时间都在同一范围内。这是输出之一:

Copy: 36299550
Move: 35762602

我尝试使用长度为 285604 个字符的字符串,结果相同。

问题:为什么“复制”构造函数 Editor(std::string& text) : _text {text} {} 这么快?它实际上不会创建输入字符串的拷贝吗?

更新 我使用以下行运行此处给出的基准测试:g++ -std=c++1z -O2 main.cpp && ./a.out

更新 2 修复移动构造函数,正如@Caleth 建议的那样(从 const std::string&& text 中删除 const)改进了一些东西!

Editor(std::string&& text) : _text {std::move(text)} {}

现在基准看起来像:

Copy: 938647
Move: 64

最佳答案

它还取决于您的优化标志。如果不进行优化,您可能会(and I did!)得到更差的移动结果:

Copy: 4164540
Move: 6344331

使用 -O2 优化运行相同的代码会得到截然不同的结果:

Copy: 1264581
Move: 791

上观看直播 Wandbox .

那是 clang 9.0。在 GCC 9.1 上,-O2 和 -O3 的差异大致相同,但 not quite as stark between copy and move :

Copy: 775
Move: 508

我猜这是一个 small string optimization开始。

一般来说,标准库中的容器在优化时效果最好,因为它们有很多小函数,编译器可以在要求时轻松内联和折叠。

同样在第一个构造函数中,per Herb Sutter , “如果您无论如何都要复制参数,最好按值传递只读参数,因为它可以从右值参数移动。”


更新:对于非常长的字符串(300k 字符),结果与上面类似(现在使用 std::chrono::duration 以毫秒为单位以避免 int溢出)with GCC 9.1 and optimizations :

Copy: 22560
Move: 1371

without optimizations :

Copy: 22259
Move: 1404

关于C++构造函数性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56292370/

相关文章:

C++ 等同于 Python len() 函数?

C++ Visual Studio, 'vc_attributes::YesNoMaybe' : 'enum' type redefinition error

c++ - 如何在运行时检查 void* 是否为 IUnknown*?

c++ - 带有引用的多态性不符合预期

C++ 两个类在构造函数中需要彼此?

c++ - 针对编译时常量优化的函数

c++ - 如何在 C++ 中循环访问自定义列表

c++,调用函数时不带(),什么意思?

c++ - "Operation not permitted"尝试执行已编译的 C++

c++ - 简单 QMainWindow 代码的菜单栏不显示,Qt Creator Mac OS