是std :: function比自动存储lambda函数更重要

问题描述 投票:5回答:2

我听说std::function的成本比auto更重要,以处理lambda函数。有效的现代c ++ item5。我想要的是澄清为什么std::function使用比auto更多的内存和一些示例代码的机制。有人能帮帮我吗?

编辑

class Widget {
public:
  Widget(int i) : i_(i) {}
  bool operator<(const Widget& o) { return o.value() > i_; }
  int value() const { return i_; };
private:
  int i_;
  int dummy_[1024];
};

int main() {
  // performance difference between auto and std::function
  { 
    auto less1 = [](const auto& p1, const auto& p2) {
      return *p1 < *p2;
    };
    std::cout << "size of less1: " << sizeof(less1) << endl;

    function<bool(const std::unique_ptr<Widget>&,
                  const std::unique_ptr<Widget>&)>
        less2 = [](const std::unique_ptr<Widget>& p1,
                   const std::unique_ptr<Widget>& p2) {
          return *p1 < *p2;
        };
    std::cout << "size of less2: " << sizeof(less2) << endl;

    {
      // auto
      std::vector<std::unique_ptr<Widget>> ws1;
      for (auto i = 0; i < 1024*100; ++i) {
        ws1.emplace_back(new Widget(std::rand()));
      }

      auto start = std::chrono::high_resolution_clock::now();
      std::sort(ws1.begin(), ws1.end(), less1);
      auto end = std::chrono::high_resolution_clock::now();
      cout << ws1[0].get()->value() << " time: " << (end - start).count() << endl;
    }

    {
      // std::function
      // 25% slower than using auto
      std::vector<std::unique_ptr<Widget>> ws2;
      for (auto i = 0; i < 1024*100; ++i) {
        ws2.emplace_back(new Widget(std::rand()));
      }

      auto start = std::chrono::high_resolution_clock::now();
      std::sort(ws2.begin(), ws2.end(), less2);
      auto end = std::chrono::high_resolution_clock::now();
      cout << ws2[0].get()->value() << " time: " << (end - start).count() << endl;
    }
  }
  return 0;
}

它来自https://github.com/danielhongwoo/mec/blob/master/item5/item5.cpp

我认为这段代码告诉我使用std::function比使用auto慢。但不是使用内存。我只想用一些真实的代码来证明它。

c++ c++11 lambda auto std-function
2个回答
8
投票

std::function可以存储任意可调用的。因此,必须进行类型擦除以能够存储任意类型的东西。这可能需要在一般情况下进行动态分配,并且它肯定需要在每次调用operator ()时进行间接调用(虚拟调用或通过函数指针调用)。

lambda表达式的类型不是std::function,它是一个未命名的类类型,定义了operator()(lambda的闭包类型)。使用auto a存储lambda使得a的类型成为这种精确的闭包类型,没有开销。


0
投票

std::function的内存成本是真实的。正如我在RHEL 64位机器上测试的那样,它是32字节,而lambda只需要1个字节。但是为了提高运行效率,原始成本中的注释无法再现。

使用g++ -std=c++17 -O2,我实际上比lambda快得多std::function。使用g++ -std=c++14 -O2,结果很接近,但lambda仍然落后。

size of less1 as lambda: 1
size of less2 as function : 32
3722 time lambda sort: 47979086
6700 time function sort: 45291861
© www.soinside.com 2019 - 2024. All rights reserved.