2016-04-28 21 views
4

bewegen Gibt es einen Unterschied zwischen:std :: mit std :: make_pair

std::map <int,std::pair<T,T>> m; 
T t1,t2; 
m.emplace(1,std::make_pair(t1,t2)); 

und:

std::map <int,std::pair<T,T>> m; 
T t1,t2; 
m.emplace(1,std::move(std::make_pair(t1,t2))); 

Ist std::move hier überflüssig? Will std::map::emplace und perfect forwarding kümmern sich um die std::pair direkt in der std::map?

+0

Hier sind zwei 'std :: -Paare beteiligt. –

Antwort

9

std::make_pair(...) und std::move(std::make_pair(...)) sind beide rvalue Ausdrücke (der erste ist ein prvalue, der zweite ist ein xvalue). Da emplace Forwarding-Referenzen übernimmt, werden beide als gleicher Typ abgeleitet, so dass std::move in diesem Fall redundant ist, aber in einem generellen Fall kann ein redundanter std::move Kopier-Elision verhindern.

m.emplace(1, std::make_pair(t1, t2)); 

entspricht:

auto&& arg = std::make_pair(t1, t2); 
std::pair<const int, std::pair<T, T>> e(1, std::forward<std::pair<T, T>>(arg)); 

die die folgende Initialisierung des Wertes des Kartenelement durchführt:

auto&& arg = std::make_pair(t1, t2); 
std::pair<T, T> p(std::forward<std::pair<T, T>>(arg)); 

anzumerken, dass diese aus unterschiedlichen ist:

std::pair<T, T> p(t1, t2); 

Die Form r erzeugt zuerst ein Prvalue-Paar (erstellt Kopien von t1 und t2), von dem dann die (t1 und t2 in p kopierten) verschoben werden. Es findet keine Kopier-Elision statt.

Letzterer verwendet t1 und t2, um beide im Paar gespeicherten T s zu initialisieren.

Um eine unnötige Bewegung zu vermeiden, die aus der ersten Syntax führt, Sie stattdessen stückweise Konstruktion nutzen können:

m.emplace(std::piecewise_construct 
     , std::forward_as_tuple(1) 
     , std::forward_as_tuple(t1, t2)); 

, die gleichwertig sein wird:

auto&& arg = std::tuple<T&, T&>(t1, t2); 
std::pair<T, T> p(std::get<0>(std::forward<std::tuple<T&, T&>>(arg)) 
       , std::get<1>(std::forward<std::tuple<T&, T&>>(arg))); 

, die die Elemente des Paares initialisieren wird von Referenzmitgliedern, die an Original t1 und t2 gebunden sind.

0
m.emplace(std::make_pair(1, std::make_pair(t1,t2))); 

wird Move Konstruktor aufrufen.

+0

In diesem Fall ist es besser, stückweise zu konstruieren, was zu keinen Verschiebungen * oder * Kopien führt. –