为什么emplace_back比push_back快? [英] Why emplace_back is faster than push_back?
问题描述
我认为 emplace_back
将是获胜者,在做这样的事情时:
code> v.push_back(myClass(arg1,arg2));
因为 emplace_back
向量,而 push_back
,将首先构造一个匿名对象,然后将其复制到向量。有关更多信息,请参阅此问题。
这里是实验代码:
#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 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 takes me< time_span.count()<< seconds。;
std :: cout<< std :: endl;
vector< int> v2;
t1 = high_resolution_clock :: now();
for(size_t i = 0; i v2.emplace_back(i);
t2 = high_resolution_clock :: now();
time_span = duration_cast< duration< double>>(t2-t1);
std :: cout<< emplace_back takes me< time_span.count()<< seconds。;
std :: cout<< std :: endl;
return 0;
}
结果是 emplace_back
更快。
push_back取了我2.76127秒。
emplace_back花了我1.99151秒。
为什么?第一个链接问题的答案清楚地表明,没有性能差异。
也尝试过其他时间方法,但结果相同。
评论说,使用 int
的测试没有说什么, push_back
需要一个参考
我在上面的代码中做了相同的测试,但是不是 int
我有一个类 A
:
A类{
public:
A(int a) :a(a){}
private:
int a;
};
结果:
code> push_back拿了我6.92313秒。
emplace_back花了我6.1815秒。
denlan说,我也应该改变操作的位置,所以我换了他们,在这两种情况下(
int
和A类$ c $
[解决方案]
$ b $ b我在
调试模式
中运行代码,这使得测量无效。对于基准测试,始终运行发布模式
中的代码。解决方案测试用例不是很有帮助。
push_back
使用一个容器元素并将其复制/移动到容器中。emplace_back
从这些新的容器元素获取任意参数和构造。但是如果你将一个已经是元素类型的参数传给emplace_back
,你只需要使用copy / move构造函数。
这是一个更好的比较:
Foo x;条y; Zip z;
v.push_back(T(x,y,z)); // make temporary,push it back
v.emplace_back(x,y,z); //没有临时,直接构造T(x,y,z)到位
但是
emplace_back
会执行显式转换: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
的其他结构也很不错:std :: vector< std :: thread>线程;
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)
I thought that
emplace_back
would be the winner, when doing something like this:v.push_back(myClass(arg1, arg2));
because
emplace_back
would construct the object immediately in the vector, whilepush_back
, would first construct an anonymous object and then would copy it to the vector. For more see this question.Google also gives this and this questions.
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.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 from my pesudo-site, but identical results.
[EDIT] Comments say that testing with
int
s doesn't say anything and thatpush_back
takes a ref.I did the same test in the code above, but instead of
int
I had a classA
: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]
As denlan said, I should also change the position of the operations, so I swapped them and in both situation (
int
andclass A
),emplace_back
was again the winner.[SOLUTION]
I was running the code in
debug mode
, which makes the measurements invalid. For benchmarking, always run the code inrelease mode
.解决方案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 toemplace_back
, you'll just use the copy/move constructor anyway.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 explicit conversions: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 withemplace
, too: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)
这篇关于为什么emplace_back比push_back快?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!