2014-05-17 2 views
22

나는 emplace_back가 승자가 될 것이라고 생각, 같은 것을 할 때 :에 복사 할 다음, 벡터에서 즉시 개체를 생성 할 push_back 동안, 먼저 익명 객체를 생성 것이며왜 emplace_back이 push_back보다 빠릅니까?

v.push_back(myClass(arg1, arg2)); 

emplace_back 때문에를 벡터. 자세한 내용은 this을 참조하십시오.

Google은 또한 thisthis 개의 질문을 제공합니다.

정수로 채워지는 벡터를 비교하기로했습니다.

#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가 빠른 것입니다 : 여기

실험 코드입니다.

push_back took me 2.76127 seconds. 
emplace_back took me 1.99151 seconds. 

왜? 첫 번째 연결된 질문의 대답은 성능 차이가 없다고 분명히 말합니다.

다른 페어 사이트에서 time methods과 시도했지만 동일한 결과가 나타납니다.

[편집] 의견은 int으로 테스트하는 것은 아무 말도하지 않으며 그 push_back은 ref를 취한다고 말합니다.

나는 위의 코드에서 동일한 테스트를했지만 대신 int의 I 클래스 A했다 :

class A { 
public: 
    A(int a) : a(a) {} 
private: 
    int a; 
}; 

결과 :

push_back took me 6.92313 seconds. 
emplace_back took me 6.1815 seconds. 

[EDIT.2]

로를 denlan 말했다, 나는 또한 작업의 위치를 ​​변경해야하므로, 나는 두 상황 (intclass A), emplace_back가 다시 우승했습니다.

[솔루션]

내가 측정이 유효하게 debug mode의 코드를 실행했다. 벤치마킹의 경우 코드를 항상 release mode에서 실행하십시오.

답변

37

테스트 케이스가별로 도움이되지 않습니다. push_back은 컨테이너 요소를 가져 와서 컨테이너로 복사/이동합니다. emplace_back은 새 컨테이너 요소에서 임의의 인수와 구문을 취합니다. 그러나 이미 요소 유형 인 단일 인수를 emplace_back으로 전달하면 복사/이동 생성자 만 사용합니다.

여기에 더 나은 비교입니다 :

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명시 적 변환을 수행한다는 것입니다 : 때를

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; 
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) 
관련 문제