2014-05-17 15 views
22

Ho pensato che emplace_back sarebbe stato il vincitore, quando si fa qualcosa di simile:Perché emplace_back è più veloce di push_back?

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

perché emplace_back sarebbe costruire l'oggetto immediatamente nel vettore, mentre push_back, avrebbe prima costruire un oggetto anonimo e poi sarebbe copiarlo il vettore. Per ulteriori informazioni, vedere la domanda this.

Google dà anche this e this domande.

ho deciso di confrontarli per un vettore che sarebbe stato riempito da numeri interi.

ecco il codice dell'esperimento:

#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; 
} 

Il risultato è che emplace_back è più veloce.

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

Perché? La risposta della prima domanda collegata dice chiaramente che non ci saranno differenze di prestazioni.

provato anche con altri time methods dal mio pesudo-sito, ma risultati identici.

[EDIT] Commenti dire che il test con int s non dice nulla e che push_back prende un rif.

ho fatto lo stesso test nel codice di cui sopra, ma invece di int ho avuto una classe A:

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

risultati:

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

[EDIT.2]

Come denlan detto, devo anche cambiare la posizione delle operazioni, così ho scambiato e in entrambi situazione (int e class A), emplace_back è stato ancora il vincitore.

[SOLUZIONE]

stavo correndo il codice debug mode, il che rende le misurazioni valide. Per il benchmarking, eseguire sempre il codice in release mode.

risposta

37

Il test case non è molto utile. push_back prende un elemento contenitore e lo copia/sposta nel contenitore. emplace_back prende argomenti arbitrari e costruisce da quelli un nuovo elemento contenitore. Ma se passi un singolo argomento che è già di tipo elemento su emplace_back, dovrai comunque utilizzare il costruttore copia/sposta.

Ecco un confronto migliore:

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 

La differenza fondamentale, tuttavia, è che emplace_back esegue espliciti conversioni:

std::vector<std::unique_ptr<Foo>> v; 
v.emplace_back(new Foo(1, 'x', true)); // constructor is explicit! 

questo esempio verrà leggermente forzato in futuro, quando si dovrebbe dire v.push_back(std::make_unique<Foo>(1, 'x', true)). Tuttavia, altre costruzioni sono molto belle con 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) 
Problemi correlati