C++ 为什么 emplace_back 比 push_back 快?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23717151/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why emplace_back is faster than push_back?
提问by gsamaras
I thought that emplace_back
would be the winner, when doing something like this:
emplace_back
当做这样的事情时,我认为这将是赢家:
v.push_back(myClass(arg1, arg2));
because emplace_back
would construct the object immediately in the vector, while push_back
, would first construct an anonymous object and then would copy it to the vector. For more see thisquestion.
因为emplace_back
会立即在向量中构造对象,而push_back
, 将首先构造一个匿名对象,然后将其复制到向量中。有关更多信息,请参阅此问题。
Google also gives thisand thisquestions.
I decided to compare them for a vector that would be filled by integers.
我决定将它们与一个由整数填充的向量进行比较。
Here is the experiment code:
下面是实验代码:
#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;
}
The result is that emplace_back
is faster.
结果emplace_back
是更快。
push_back took me 2.76127 seconds.
emplace_back took me 1.99151 seconds.
Why? The answer of the 1st linked question clearly says that there will be no performance difference.
为什么?第一个链接问题的答案清楚地表明不会有性能差异。
Also tried with other time methods, but got identical results.
还尝试了其他时间方法,但得到了相同的结果。
[EDIT]
Comments say that testing with int
s doesn't say anything and that push_back
takes a ref.
[编辑] 评论说用int
s测试什么也没说,这push_back
需要参考。
I did the same test in the code above, but instead of int
I had a class A
:
我在上面的代码中做了同样的测试,但不是int
我有一个类A
:
class A {
public:
A(int a) : a(a) {}
private:
int a;
};
Result:
结果:
push_back took me 6.92313 seconds.
emplace_back took me 6.1815 seconds.
[EDIT.2]
[编辑 2]
As denlan said, I should also change the position of the operations, so I swapped them and in both situation (int
and class A
), emplace_back
was again the winner.
正如 denlan 所说,我也应该改变操作的位置,所以我交换了它们,在两种情况下(int
和class A
),emplace_back
再次成为赢家。
[SOLUTION]
[解决方案]
I was running the code in debug mode
, which makes the measurements invalid. For benchmarking, always run the code in release mode
.
我在 中运行代码debug mode
,这使得测量无效。对于基准测试,始终在release mode
.
回答by Kerrek SB
Your test case isn't very helpful. push_back
takes a container element and copies/moves it into the container. emplace_back
takes arbitrary arguments and constructs from those a new container element. But if you pass a single argument that's already of element type to emplace_back
, you'll just use the copy/move constructor anyway.
你的测试用例不是很有帮助。push_back
获取一个容器元素并将其复制/移动到容器中。emplace_back
接受任意参数并从这些参数中构造一个新的容器元素。但是,如果您将已经属于元素类型的单个参数传递给emplace_back
,则无论如何您都将只使用复制/移动构造函数。
Here's a better comparison:
这是一个更好的比较:
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
The key difference, however, is that emplace_back
performs explicitconversions:
但是,关键区别在于emplace_back
执行显式转换:
std::vector<std::unique_ptr<Foo>> v;
v.emplace_back(new Foo(1, 'x', true)); // constructor is explicit!
This example will be mildly contrived in the future, when you should say v.push_back(std::make_unique<Foo>(1, 'x', true))
. However, other constructions are very nice with emplace
, too:
这个例子将来会稍微做作,当你应该说v.push_back(std::make_unique<Foo>(1, 'x', true))
. 但是,其他结构也非常适合emplace
:
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)