W C ++ 11 możesz prawie całkowicie obejść się bez make_pair. Zobacz moją odpowiedź .
PlagueHammer
2
W C ++ 17 std::make_pairjest zbędny. Poniżej znajduje się odpowiedź, która szczegółowo to wyjaśnia.
Drew Dormann
Odpowiedzi:
165
Różnica polega na tym, std::pairże musisz określić typy obu elementów, podczas gdy std::make_pairutworzysz parę z typem elementów, które są do niego przekazywane, bez konieczności mówienia. Tak czy inaczej mogłem zebrać z różnych dokumentów.
W rzeczywistości typy powinny być wywnioskowane w czasie kompilacji bez potrzeby określania.
Czad,
@Tor Tak, wiem, jak używać obu z nich, byłem po prostu ciekawy, czy był ku temu powód std::make_pair. Najwyraźniej to tylko dla wygody.
@Jay Tak by się wydawało.
Tor Valamo,
15
Myślę, że możesz to zrobić w one = {10, 20}dzisiejszych czasach, ale nie mam pod ręką kompilatora C ++ 11, aby to sprawdzić.
MSalters
6
Należy również pamiętać, że make_pairdziała z nienazwanymi typami, w tym strukturami, związkami, lambdami i innymi elementami dekoracyjnymi.
Mooing Duck
35
Jak @MSalters odpowiedział powyżej, możesz teraz użyć nawiasów klamrowych, aby to zrobić w C ++ 11 (właśnie zweryfikowano to za pomocą kompilatora C ++ 11):
main.cpp:Infunction‘int main()’:
main.cpp:13:13: error: missing template arguments before ‘my_class’MyClass my_class(1);^~~~~~~~
i zamiast tego wymaga pracy:
MyClass<int> my_class(1);
lub pomocnik:
auto my_class = make_my_class(1);
który używa zwykłej funkcji zamiast konstruktora.
Różnica dla `std :: reference_wrapper
Ten komentarz wspomina, że std::make_pairrozpakowuje się, std::reference_wrapperpodczas gdy konstruktor tego nie robi, więc to jedna różnica. Przykład TODO.
„C ++ 17 umożliwia taką składnię, a zatem make_pair jest zbędna”. - Dlaczego std::make_pairnie stało się przestarzałe w C ++ 17?
andreee
@andreee Nie jestem pewien, możliwym powodem jest to, że nie stwarza problemów, więc nie ma potrzeby łamania starego kodu? Ale nie jestem zaznajomiony z uzasadnieniem komitetu C ++, daj mi znać, jeśli coś znajdziesz.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
1
Jedną z przydatnych rzeczy, na które się natknąłem, jest to, że możliwość określenia typów za pomocą std :: make_pair <T1, T2> (o1, o2) zapobiega popełnieniu przez użytkownika błędu przekazywania typów o1 lub o2, które nie mogą być niejawnie rzut do T1 lub T2. Na przykład przekazanie liczby ujemnej do liczby int bez znaku. -Wsign-conversion -Werror nie wychwyci tego błędu z konstruktorem std :: pair w c ++ 11, jednak przechwyci błąd, jeśli zostanie użyte std :: make_pair.
conchoecia
make_pairrozpakowuje opakowania referencyjne, więc w rzeczywistości różni się od CTAD.
LF
26
Nie ma różnicy między użyciem make_paira jawnym wywołaniem pairkonstruktora z określonymi argumentami typu. std::make_pairjest wygodniejsze, gdy typy są rozwlekłe, ponieważ metoda szablonu ma dedukcję typu na podstawie podanych parametrów. Na przykład,
Warto zauważyć, że jest to powszechny idiom w programowaniu szablonów w C ++. Jest znany jako idiom Object Generator, możesz znaleźć więcej informacji i ładny przykład tutaj .
Edycja Jak ktoś zasugerował w komentarzach (od czasu usunięcia), poniżej znajduje się nieznacznie zmodyfikowany wyciąg z łącza na wypadek, gdyby się zepsuł.
Generator obiektów umożliwia tworzenie obiektów bez jawnego określania ich typów. Opiera się on na użytecznej właściwości szablonów funkcji, których szablony klas nie mają: parametry typu szablonu funkcji są wyprowadzane automatycznie z jego rzeczywistych parametrów. std::make_pairto prosty przykład, który zwraca wystąpienie std::pairszablonu w zależności od rzeczywistych parametrów std::make_pairfunkcji.
make_pair tworzy dodatkową kopię nad konstruktorem direct. Zawsze wpisuję moje pary, aby zapewnić prostą składnię.
To pokazuje różnicę (przykład autorstwa Rampala Chaudhary):
Jestem prawie pewien, że dodatkowa kopia zostanie usunięta we wszystkich przypadkach, jeśli ustawienia optymalizacji kompilatora są wystarczająco wysokie.
Björn Pollex
1
Dlaczego miałbyś kiedykolwiek chcieć polegać na optymalizacji kompilatora pod kątem poprawności?
sjbx
Uzyskuję te same wyniki w przypadku obu wersji i std::movetylko w środku inserti / lub w pobliżu tego, do czego byłoby odniesienie sample. Dopiero gdy zmieniam std::map<int,Sample>na std::map<int,Sample const&>to zmniejszam liczbę konstruowanych obiektów i dopiero kiedy usuwam konstruktor kopiujący, eliminuję wszystkie kopie (oczywiście). Po wprowadzeniu obu tych zmian mój wynik obejmuje jedno wywołanie domyślnego konstruktora i dwa wywołania destruktora dla tego samego obiektu. Myślę, że czegoś mi brakuje. (g ++ 5.4.1, c ++ 11)
John P
FWIW Zgadzam się, że optymalizacja i poprawność powinny być całkowicie niezależne, ponieważ dokładnie taki kod piszesz w celu sprawdzenia poprawności po tym, jak różne poziomy optymalizacji dają niespójne wyniki. Ogólnie rzecz biorąc, polecałbym emplacezamiast insertkonstruować wartość do natychmiastowego wstawienia (i nie chcesz dodatkowych instancji). To nie jest moja specjalizacja, jeśli mogę nawet powiedzieć, że ją mam, ale kopiuj / przenieś semantyka wprowadzona przez C ++ 11 bardzo mi pomogła.
John P
Wydaje mi się, że napotykam dokładnie ten sam problem i po debugowaniu przez prawie cały wieczór w końcu tu dotarłem.
lllllllllllll
1
zaczynając od c ++ 11 po prostu użyj jednolitej inicjalizacji dla par. Więc zamiast:
{1, 2}może być użyty do zainicjowania pary, ale nie zatwierdza dla pary typów. Czyli przy użyciu auto trzeba zobowiązać się do określonego typu na RHS: auto p = std::pair{"Tokyo"s, 9.00};.
std::make_pair
jest zbędny. Poniżej znajduje się odpowiedź, która szczegółowo to wyjaśnia.Odpowiedzi:
Różnica polega na tym,
std::pair
że musisz określić typy obu elementów, podczas gdystd::make_pair
utworzysz parę z typem elementów, które są do niego przekazywane, bez konieczności mówienia. Tak czy inaczej mogłem zebrać z różnych dokumentów.Zobacz ten przykład z http://www.cplusplus.com/reference/std/utility/make_pair/
Oprócz niejawnej premii za konwersję, jeśli nie używasz make_pair, musisz to zrobić
za każdym razem, gdy przydzielasz do jednego, co byłoby denerwujące z czasem ...
źródło
std::make_pair
. Najwyraźniej to tylko dla wygody.one = {10, 20}
dzisiejszych czasach, ale nie mam pod ręką kompilatora C ++ 11, aby to sprawdzić.make_pair
działa z nienazwanymi typami, w tym strukturami, związkami, lambdami i innymi elementami dekoracyjnymi.Jak @MSalters odpowiedział powyżej, możesz teraz użyć nawiasów klamrowych, aby to zrobić w C ++ 11 (właśnie zweryfikowano to za pomocą kompilatora C ++ 11):
źródło
Nie można wywnioskować argumentów szablonu klasy z konstruktora przed C ++ 17
Przed C ++ 17 nie można było napisać czegoś takiego:
ponieważ mogłoby to wywnioskować typy szablonów z argumentów konstruktora.
C ++ 17 umożliwia taką składnię, a zatem jest
make_pair
zbędna.Przed C ++ 17
std::make_pair
pozwalało nam pisać mniej rozwlekły kod:zamiast bardziej rozwlekłych:
który powtarza typy i może być bardzo długi.
Wnioskowanie o typie działa w tym przypadku sprzed wersji C ++ 17, ponieważ
make_pair
nie jest konstruktorem.make_pair
jest zasadniczo równoważne z:To samo odnosi się do koncepcji
inserter
vsinsert_iterator
.Zobacz też:
Minimalny przykład
Aby uczynić rzeczy bardziej konkretnymi, możemy zaobserwować problem w minimalnym stopniu:
main.cpp
następnie:
kompiluje się szczęśliwie, ale:
zawodzi z:
i zamiast tego wymaga pracy:
lub pomocnik:
który używa zwykłej funkcji zamiast konstruktora.
Różnica dla `std :: reference_wrapper
Ten komentarz wspomina, że
std::make_pair
rozpakowuje się,std::reference_wrapper
podczas gdy konstruktor tego nie robi, więc to jedna różnica. Przykład TODO.Testowane z GCC 8.1.0, Ubuntu 16.04 .
źródło
std::make_pair
nie stało się przestarzałe w C ++ 17?make_pair
rozpakowuje opakowania referencyjne, więc w rzeczywistości różni się od CTAD.Nie ma różnicy między użyciem
make_pair
a jawnym wywołaniempair
konstruktora z określonymi argumentami typu.std::make_pair
jest wygodniejsze, gdy typy są rozwlekłe, ponieważ metoda szablonu ma dedukcję typu na podstawie podanych parametrów. Na przykład,źródło
Warto zauważyć, że jest to powszechny idiom w programowaniu szablonów w C ++. Jest znany jako idiom Object Generator, możesz znaleźć więcej informacji i ładny przykład tutaj .
Edycja Jak ktoś zasugerował w komentarzach (od czasu usunięcia), poniżej znajduje się nieznacznie zmodyfikowany wyciąg z łącza na wypadek, gdyby się zepsuł.
Generator obiektów umożliwia tworzenie obiektów bez jawnego określania ich typów. Opiera się on na użytecznej właściwości szablonów funkcji, których szablony klas nie mają: parametry typu szablonu funkcji są wyprowadzane automatycznie z jego rzeczywistych parametrów.
std::make_pair
to prosty przykład, który zwraca wystąpieniestd::pair
szablonu w zależności od rzeczywistych parametrówstd::make_pair
funkcji.źródło
&&
od C ++ 11.make_pair tworzy dodatkową kopię nad konstruktorem direct. Zawsze wpisuję moje pary, aby zapewnić prostą składnię.
To pokazuje różnicę (przykład autorstwa Rampala Chaudhary):
źródło
std::move
tylko w środkuinsert
i / lub w pobliżu tego, do czego byłoby odniesieniesample
. Dopiero gdy zmieniamstd::map<int,Sample>
nastd::map<int,Sample const&>
to zmniejszam liczbę konstruowanych obiektów i dopiero kiedy usuwam konstruktor kopiujący, eliminuję wszystkie kopie (oczywiście). Po wprowadzeniu obu tych zmian mój wynik obejmuje jedno wywołanie domyślnego konstruktora i dwa wywołania destruktora dla tego samego obiektu. Myślę, że czegoś mi brakuje. (g ++ 5.4.1, c ++ 11)emplace
zamiastinsert
konstruować wartość do natychmiastowego wstawienia (i nie chcesz dodatkowych instancji). To nie jest moja specjalizacja, jeśli mogę nawet powiedzieć, że ją mam, ale kopiuj / przenieś semantyka wprowadzona przez C ++ 11 bardzo mi pomogła.zaczynając od c ++ 11 po prostu użyj jednolitej inicjalizacji dla par. Więc zamiast:
lub
po prostu użyj
źródło
{1, 2}
może być użyty do zainicjowania pary, ale nie zatwierdza dla pary typów. Czyli przy użyciu auto trzeba zobowiązać się do określonego typu na RHS:auto p = std::pair{"Tokyo"s, 9.00};
.