2013-04-03 18 views
12

Avere una solita base -> gerarchia derivata, come:Devo usare C++ 11 emplace_back con i contatori di contatori?

class Fruit { ... }; 
class Pear : Fruit { ... }; 
class Tomato : Fruit { ... }; 

std::vector<Fruit*> m_fruits; 

ha senso (per esempio: ha prestazioni migliori) da utilizzare al posto di emplace_back push_back?

std::vector::emplace_back(new Pear()); 
std::vector::emplace_back(new Tomato()); 
+2

non si sa fino a quando non si marca/profilo –

+5

Utilizzare 'std :: vector >' per evitare perdite di memoria, la risposta è ovvia. – ipc

+0

Mi rendo conto che emplace_back si costruisce da solo l'oggetto, ma nel caso dei puntatori, non ne ho idea se abbia senso. – Zhen

risposta

9

puntatori sono tipi scalari e tipi pertanto letterali e così copiare, spostare e colloco costruzione (da un Ivalue o rvalue) sono tutti equivalenti e sarà solitamente compilare in codice identico (uno scalare copia). push_back è più chiaro che si sta eseguendo una copia scalare, mentre emplace_back deve essere riservato per la costruzione di emplace chiamando un costruttore non-copy- o move- (ad esempio un costruttore di conversione o multi-argomento).

Se il vettore dovrebbe tenere std::unique_ptr<Fruit> invece di puntatori prime (per evitare perdite di memoria), allora perché si sta chiamando un costruttore di conversione emplace_back sarebbe più corretto. Tuttavia, ciò può ancora verificarsi se l'estensione del vettore fallisce, quindi in tal caso è necessario utilizzare push_back(make_unique<Pear>()) ecc.

+0

make_unique non è nello standar e sembra che emplace_back sia lo stesso di push_back (std :: move (X)) [sto usando gcc 4.7] – Zhen

+2

@Zhen: Può sembrare così, ma non lo è. 'emplace_back (new T())' can * leak *, mentre 'push_back (make_unique ())' impossibile. E sì, 'make_unique' manca alla supervisione, puoi trovare implementazioni sul web. – GManNickG

+1

'std :: make_unique()' è stato aggiunto in C++ 14. –

13

Non utilizzare puntatori prime, utilizzare std::unique_ptr come questo:

std::vector<std::unique_ptr<Fruit>> m_fruits; 

E come non si può copiare costruire un std::unique_ptr è necessario utilizzare emplace_back (anche se è possibile utilizzare push_back con std::move).

 
m_fruits.emplace_back(new Pear()); 
m_fruits.emplace_back(new Tomato()); 

Edit:

Come sembra che utilizzando std::vector<std::unique_ptr<T>>::emplace_back e new può fuoriuscire se le std::vector esigenze e non riesce a riallocare la memoria, il mio approccio raccomandato (fino al C++ 14 introduce std::make_unique) è quello di utilizzare push_back come questo:

m_fruits.push_back(std::unique_ptr<Fruit>(new Pear)); 
m_fruits.push_back(std::unique_ptr<Fruit>(new Tomato)); 

Oppure usando std::make_unique:

m_fruits.push_back(std::make_unique<Pear>()); 
m_fruits.push_back(std::make_unique<Tomato>()); 
Problemi correlati