Di C ++ 11, Anda hampir seluruhnya dapat melakukannya tanpa make_pair. Lihat jawaban saya .
PlagueHammer
2
Dalam C ++ 17, std::make_pairberlebihan. Ada jawaban di bawah ini yang merinci ini.
Drew Dormann
Jawaban:
165
Perbedaannya adalah bahwa dengan std::pairAnda perlu menentukan jenis kedua elemen, sedangkan std::make_pairakan membuat pasangan dengan jenis elemen yang diteruskan ke sana, tanpa Anda perlu mengatakannya. Itu yang bisa saya kumpulkan dari berbagai dokumen.
Sebenarnya, jenis harus disimpulkan pada waktu kompilasi tanpa perlu menentukan.
Chad
@Tor Ya, saya tahu cara menggunakan keduanya, saya hanya ingin tahu apakah ada alasan untuk itu std::make_pair. Ternyata itu hanya untuk kenyamanan.
@ Jay Akan muncul begitu.
Tor Valamo
15
Saya pikir Anda dapat melakukannya one = {10, 20}saat ini tetapi saya tidak memiliki kompiler C ++ 11 yang berguna untuk memeriksanya.
MSalters
6
Perhatikan juga bahwa make_pairbekerja dengan jenis yang tidak disebutkan namanya, termasuk struct, serikat pekerja, lambdas, dan barang-barang kecil lainnya.
Mooing Duck
35
Seperti @MSalters menjawab di atas, Anda sekarang dapat menggunakan kurung kurawal untuk melakukan ini di C ++ 11 (cukup verifikasi ini dengan kompiler C ++ 11):
"C ++ 17 membuat sintaks itu mungkin, dan karenanya make_pair redundan." - Mengapa std::make_pairtidak usang di C ++ 17?
andreee
@ dan saya tidak yakin, alasan yang mungkin adalah tidak ada masalah sehingga tidak perlu memecahkan kode lama? Tapi saya tidak terbiasa dengan alasan komite C ++, ping saya jika Anda menemukan sesuatu.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
1
Satu hal berguna yang saya temui adalah kemampuan untuk menentukan tipe dengan std :: make_pair <T1, T2> (o1, o2) mencegah pengguna membuat kesalahan dengan meneruskan tipe o1 atau o2 yang tidak dapat secara implisit menjadi dilemparkan ke T1 atau T2. Misalnya melewati angka negatif ke int yang tidak ditandatangani. -Wsign-conversion -Werror tidak akan menangkap kesalahan ini dengan std :: pair constructor di c ++ 11 namun akan menangkap kesalahan jika std :: make_pair digunakan.
conchoecia
make_pairmembuka bungkus pembungkus referensi, jadi sebenarnya berbeda dari CTAD.
LF
26
Tidak ada perbedaan antara menggunakan make_pairdan secara eksplisit memanggil pairkonstruktor dengan argumen tipe tertentu. std::make_pairlebih nyaman ketika jenis verbose karena metode templat memiliki tipe deduksi berdasarkan parameter yang diberikan. Sebagai contoh,
Perlu dicatat bahwa ini adalah idiom umum dalam pemrograman template C ++. Ini dikenal sebagai idiom Object Generator, Anda dapat menemukan informasi lebih lanjut dan contoh yang bagus di sini .
Edit Seperti seseorang menyarankan dalam komentar (sejak dihapus) berikut ini adalah ekstrak yang sedikit dimodifikasi dari tautan jika rusak.
Object Generator memungkinkan pembuatan objek tanpa secara spesifik menentukan jenisnya. Ini didasarkan pada properti berguna templat fungsi yang tidak dimiliki templat kelas: Parameter tipe templat fungsi disimpulkan secara otomatis dari parameter aktualnya. std::make_pairadalah contoh sederhana yang mengembalikan contoh std::pairtemplate tergantung pada parameter sebenarnya dari std::make_pairfungsi.
make_pair membuat salinan tambahan di atas konstruktor langsung. Saya selalu mengetikkan pasangan saya untuk memberikan sintaksis sederhana.
Ini menunjukkan perbedaan (contoh oleh Rampal Chaudhary):
Saya cukup yakin bahwa salinan tambahan akan hilang dalam semua kasus, jika pengaturan pengoptimalan dari kompiler cukup tinggi.
Björn Pollex
1
Mengapa Anda ingin mengandalkan optimisasi kompiler untuk kebenaran?
sjbx
Saya mendapatkan hasil yang sama dengan kedua versi, dan dengan std::movehanya di dalam insertdan / atau sekitar apa yang akan menjadi referensi sample. Hanya ketika saya mengubah std::map<int,Sample>ke std::map<int,Sample const&>saya mengurangi jumlah objek yang dibangun, dan hanya ketika saya menghapus copy constructor saya menghilangkan semua salinan (jelas). Setelah melakukan kedua perubahan tersebut, hasil saya mencakup satu panggilan ke konstruktor default dan dua panggilan ke destruktor untuk objek yang sama. Saya pikir saya pasti kehilangan sesuatu. (g ++ 5.4.1, c ++ 11)
John P
FWIW Saya setuju bahwa pengoptimalan dan kebenaran harus sepenuhnya independen, karena ini adalah jenis kode yang Anda tulis sebagai pemeriksaan kewarasan setelah tingkat pengoptimalan yang berbeda menghasilkan hasil yang tidak konsisten. Secara umum saya akan merekomendasikan emplacealih-alih insertjika Anda hanya membangun nilai untuk segera dimasukkan (dan Anda tidak ingin contoh tambahan.) Ini bukan bidang keahlian saya, jika saya dapat mengatakan saya memilikinya, tetapi salin / pindahkan semantik yang diperkenalkan oleh C ++ 11 telah banyak membantu saya.
John P
Saya percaya saya menemukan masalah yang persis sama dan setelah men-debug sekitar malam itu, saya akhirnya datang ke sini.
lllllllllllll
1
mulai dari c ++ 11 cukup gunakan inisialisasi seragam untuk pasangan. Jadi alih-alih:
{1, 2}dapat digunakan untuk menginisialisasi pasangan, tetapi tidak dilakukan untuk pasangan tipe. Yaitu ketika menggunakan auto Anda harus berkomitmen untuk tipe pada RHS: auto p = std::pair{"Tokyo"s, 9.00};.
std::make_pair
berlebihan. Ada jawaban di bawah ini yang merinci ini.Jawaban:
Perbedaannya adalah bahwa dengan
std::pair
Anda perlu menentukan jenis kedua elemen, sedangkanstd::make_pair
akan membuat pasangan dengan jenis elemen yang diteruskan ke sana, tanpa Anda perlu mengatakannya. Itu yang bisa saya kumpulkan dari berbagai dokumen.Lihat contoh ini dari http://www.cplusplus.com/reference/std/utility/make_pair/
Selain dari bonus konversi implisit, jika Anda tidak menggunakan make_pair, Anda harus melakukannya
setiap kali Anda ditugaskan ke satu, yang akan mengganggu dari waktu ke waktu ...
sumber
std::make_pair
. Ternyata itu hanya untuk kenyamanan.one = {10, 20}
saat ini tetapi saya tidak memiliki kompiler C ++ 11 yang berguna untuk memeriksanya.make_pair
bekerja dengan jenis yang tidak disebutkan namanya, termasuk struct, serikat pekerja, lambdas, dan barang-barang kecil lainnya.Seperti @MSalters menjawab di atas, Anda sekarang dapat menggunakan kurung kurawal untuk melakukan ini di C ++ 11 (cukup verifikasi ini dengan kompiler C ++ 11):
sumber
Argumen templat kelas tidak dapat disimpulkan dari konstruktor sebelum C ++ 17
Sebelum C ++ 17 Anda tidak dapat menulis sesuatu seperti:
karena itu akan menyimpulkan tipe templat dari argumen konstruktor.
C ++ 17 membuat sintaks itu mungkin, dan karena itu
make_pair
berlebihan.Sebelum C ++ 17,
std::make_pair
izinkan kami untuk menulis lebih sedikit kode verbose:alih-alih yang lebih bertele-tele:
yang mengulang jenisnya, dan bisa sangat panjang.
Ketik inferensi berfungsi dalam kasus pra-C ++ 17 karena
make_pair
bukan merupakan konstruktor.make_pair
pada dasarnya setara dengan:Konsep yang sama berlaku untuk
inserter
vsinsert_iterator
.Lihat juga:
Contoh minimal
Untuk membuat masalah lebih konkret, kita dapat mengamati masalah secara minimal dengan:
main.cpp
kemudian:
mengkompilasi dengan senang hati, tetapi:
gagal dengan:
dan sebagai gantinya mengharuskan untuk bekerja:
atau pembantu:
yang menggunakan fungsi biasa bukan konstruktor.
Perbedaan untuk `std :: reference_wrapper
Komentar ini menyebutkan bahwa
std::make_pair
membukastd::reference_wrapper
sementara konstruktor tidak, jadi itu satu perbedaan. Contoh TODO.Diuji dengan GCC 8.1.0, Ubuntu 16.04 .
sumber
std::make_pair
tidak usang di C ++ 17?make_pair
membuka bungkus pembungkus referensi, jadi sebenarnya berbeda dari CTAD.Tidak ada perbedaan antara menggunakan
make_pair
dan secara eksplisit memanggilpair
konstruktor dengan argumen tipe tertentu.std::make_pair
lebih nyaman ketika jenis verbose karena metode templat memiliki tipe deduksi berdasarkan parameter yang diberikan. Sebagai contoh,sumber
Perlu dicatat bahwa ini adalah idiom umum dalam pemrograman template C ++. Ini dikenal sebagai idiom Object Generator, Anda dapat menemukan informasi lebih lanjut dan contoh yang bagus di sini .
Edit Seperti seseorang menyarankan dalam komentar (sejak dihapus) berikut ini adalah ekstrak yang sedikit dimodifikasi dari tautan jika rusak.
Object Generator memungkinkan pembuatan objek tanpa secara spesifik menentukan jenisnya. Ini didasarkan pada properti berguna templat fungsi yang tidak dimiliki templat kelas: Parameter tipe templat fungsi disimpulkan secara otomatis dari parameter aktualnya.
std::make_pair
adalah contoh sederhana yang mengembalikan contohstd::pair
template tergantung pada parameter sebenarnya daristd::make_pair
fungsi.sumber
&&
sejak C ++ 11.make_pair membuat salinan tambahan di atas konstruktor langsung. Saya selalu mengetikkan pasangan saya untuk memberikan sintaksis sederhana.
Ini menunjukkan perbedaan (contoh oleh Rampal Chaudhary):
sumber
std::move
hanya di dalaminsert
dan / atau sekitar apa yang akan menjadi referensisample
. Hanya ketika saya mengubahstd::map<int,Sample>
kestd::map<int,Sample const&>
saya mengurangi jumlah objek yang dibangun, dan hanya ketika saya menghapus copy constructor saya menghilangkan semua salinan (jelas). Setelah melakukan kedua perubahan tersebut, hasil saya mencakup satu panggilan ke konstruktor default dan dua panggilan ke destruktor untuk objek yang sama. Saya pikir saya pasti kehilangan sesuatu. (g ++ 5.4.1, c ++ 11)emplace
alih-alihinsert
jika Anda hanya membangun nilai untuk segera dimasukkan (dan Anda tidak ingin contoh tambahan.) Ini bukan bidang keahlian saya, jika saya dapat mengatakan saya memilikinya, tetapi salin / pindahkan semantik yang diperkenalkan oleh C ++ 11 telah banyak membantu saya.mulai dari c ++ 11 cukup gunakan inisialisasi seragam untuk pasangan. Jadi alih-alih:
atau
gunakan saja
sumber
{1, 2}
dapat digunakan untuk menginisialisasi pasangan, tetapi tidak dilakukan untuk pasangan tipe. Yaitu ketika menggunakan auto Anda harus berkomitmen untuk tipe pada RHS:auto p = std::pair{"Tokyo"s, 9.00};
.