首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么emplace_back比push_back快?

为什么emplace_back比push_back快?
EN

Stack Overflow用户
提问于 2014-05-18 07:33:51
回答 1查看 50.8K关注 0票数 45

当我做这样的事情时,我认为emplace_back会是赢家:

代码语言:javascript
复制
v.push_back(myClass(arg1, arg2));

因为emplace_back会立即在矢量中构造对象,而push_back会首先构造一个匿名对象,然后将其复制到矢量中。有关更多信息,请参阅this问题。

谷歌还向thisthis提出了问题。

我决定将它们与将由整数填充的向量进行比较。

实验代码如下:

代码语言:javascript
复制
#include <iostream>
#include <vector>
#include <ctime>
#include <ratio>
#include <chrono>

using namespace std;
using namespace std::chrono;

int main() {

  vector<int> v1;

  const size_t N = 100000000;

  high_resolution_clock::time_point t1 = high_resolution_clock::now();
  for(size_t i = 0; i < N; ++i)
    v1.push_back(i);
  high_resolution_clock::time_point t2 = high_resolution_clock::now();

  duration<double> time_span = duration_cast<duration<double>>(t2 - t1);

  std::cout << "push_back took me " << time_span.count() << " seconds.";
  std::cout << std::endl;

  vector<int> v2;

  t1 = high_resolution_clock::now();
  for(size_t i = 0; i < N; ++i)
    v2.emplace_back(i);
  t2 = high_resolution_clock::now();
  time_span = duration_cast<duration<double>>(t2 - t1);
  std::cout << "emplace_back took me " << time_span.count() << " seconds.";
  std::cout << std::endl;

  return 0;
}

结果是emplace_back更快。

代码语言:javascript
复制
push_back took me 2.76127 seconds.
emplace_back took me 1.99151 seconds.

为什么?第一个链接问题的答案清楚地表明,不会有性能差异。

也尝试了其他time methods,但得到了相同的结果。

编辑评论说,使用ints测试没有说明任何问题,而push_back需要一个引用。

我在上面的代码中执行了相同的测试,但我有一个类A,而不是int

代码语言:javascript
复制
class A {
 public:
  A(int a) : a(a) {}
 private:
  int a;
};

结果:

代码语言:javascript
复制
push_back took me 6.92313 seconds.
emplace_back took me 6.1815 seconds.

EDIT.2

正如登兰所说,我也应该改变操作的位置,所以我交换了它们,在两种情况下(intclass A),emplace_back再次成为赢家。

解决方案

我在debug mode中运行代码,这会使测量结果无效。为了进行基准测试,请始终在release mode中运行代码。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-05-18 07:47:01

你的测试用例没有多大帮助。push_back获取容器元素并将其复制/移动到容器中。emplace_back接受任意的参数,并从中构造一个新的容器元素.但是,如果您将一个已经是元素类型的参数传递给emplace_back,那么无论如何都只需要使用copy/move构造函数。

下面是一个更好的比较:

代码语言:javascript
复制
Foo x; Bar y; Zip z;

v.push_back(T(x, y, z));  // make temporary, push it back
v.emplace_back(x, y, z);  // no temporary, directly construct T(x, y, z) in place

然而,关键的区别在于emplace_back执行显式转换:

代码语言:javascript
复制
std::vector<std::unique_ptr<Foo>> v;
v.emplace_back(new Foo(1, 'x', true));  // constructor is explicit!

这个示例将在将来温和地设计,那时您应该使用v.push_back(std::make_unique<Foo>(1, 'x', true))。然而,使用emplace的其他构造也非常好:

代码语言:javascript
复制
std::vector<std::thread> threads;
threads.emplace_back(do_work, 10, "foo");    // call do_work(10, "foo")
threads.emplace_back(&Foo::g, x, 20, false);  // call x.g(20, false)
票数 56
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23717151

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档