2014-09-10 13 views
19

Czy istnieje sposób umieszczenia numeru std::pair?Umieszczanie std :: pair

std::unordered_map<int, std::pair<std::string, std::string>> my_map; 
my_map.emplace(1, "foo", "bar"); // Error 

oczywiście wkładania jest możliwa:

my_map[2] = std::make_pair("bar", "foo"); 

Ale nie to wymagać zbędnego kopiowanie/przenoszenie?

Odpowiedz

19

Czy istnieje sposób na umieszczenie std :: pair?

Argumenty muszą być korzystne dla konstruktora pair<int, pair<string,string>>, mapa na value_type:

my_map.emplace(1, std::make_pair("foo", "bar")); 

Ale nie to wymagać zbędnego kopiowanie/przenoszenie?

Nie; make_pair tworzy parę wskaźników z literałami łańcuchowymi, które są następnie używane do inicjowania (w przypadku emplace) lub przypisywane do (w przypadku []) łańcuchów zawartych na mapie.

+2

rozszerzając to - 'emplace' nie tworzy obiektu, a następnie przenosi go do pojemnika; używa * przekazywania * do przekazywania argumentów do kontenera, a następnie kontener wywołuje konstruktor obiektu, gdy kontener wykryje, gdzie w pamięci chce zbudować obiekt. (Myląca nazwa funkcji!) –

0

Tak jest:

my_map.emplace(1, std::make_pair("foo", "bar")); 
16

W tym przypadku nie ma sensu emplacing części z „wartości typu” std::pair, jak std::string może zarówno być skutecznie przekształcony z C-string, a może być skutecznie przeniesiony na mapę. Proste m.emplace(3, std::make_pair("bob", "alice")) i jesteś 99% drogi do optymalnej wydajności.

Jednakże, jeśli masz std::map który mapuje się do rodzaju, które nie mogą być skutecznie skonstruowane w taki sposób, C++ 11 zapewnia std::piecewise_construct dla std::pair być emplace d.

struct A { }; // nothing 
struct C { C(C&&)=delete; }; // no copy/move 
struct B { B()=delete; B(B&&)=delete; B(C&&, C&&) {}; }; // no copy/move, only annoying ctor 

std::map< int, std::pair<A,B> > test; 
// test.emplace(0, std::make_pair(A{}, B{}); // does not compile 
// test.emplace(0, std::make_pair(A{}, B{C{},C{}}); // does not compile 
test.emplace(std::piecewise_construct, 
    std::make_tuple(0), 
    std::forward_as_tuple(
    std::piecewise_construct, 
    std::forward_as_tuple(A{}), 
    std::forward_as_tuple(C{}, C{}) 
) 
); // compiles! 

live example

Jest to skrajny przypadek rogu, jako obiekty wydajny-Move są znacznie bardziej powszechne.

+3

Er. 'std :: piecewise_construct' to C++ 11, a nie C++ 14. – Rapptz

+0

@Rapptz dobry punkt. – Yakk

Powiązane problemy