Karena C ++ 17 std::map
menawarkan dua metode penyisipan baru: insert_or_assign()
dan try_emplace()
, seperti juga disebutkan dalam komentar oleh sp2danny .
insert_or_assign()
Pada dasarnya, insert_or_assign()
ini adalah versi yang "ditingkatkan" dari operator[]
. Berbeda dengan operator[]
, insert_or_assign()
tidak mengharuskan tipe nilai peta menjadi dapat dibangun secara default. Misalnya, kode berikut tidak dapat dikompilasi, karena MyClass
tidak memiliki konstruktor default:
class MyClass {
public:
MyClass(int i) : m_i(i) {};
int m_i;
};
int main() {
std::map<int, MyClass> myMap;
// VS2017: "C2512: 'MyClass::MyClass' : no appropriate default constructor available"
// Coliru: "error: no matching function for call to 'MyClass::MyClass()"
myMap[0] = MyClass(1);
return 0;
}
Namun, jika Anda mengganti myMap[0] = MyClass(1);
dengan baris berikut, maka kode akan terkompilasi dan penyisipan berlangsung seperti yang diinginkan:
myMap.insert_or_assign(0, MyClass(1));
Selain itu, mirip dengan insert()
, insert_or_assign()
mengembalikan a pair<iterator, bool>
. Nilai Boolean adalah true
jika penyisipan terjadi dan false
jika tugas telah selesai. Iterator menunjuk ke elemen yang disisipkan atau diperbarui.
try_emplace()
Mirip dengan di atas, try_emplace()
merupakan "perbaikan" dari emplace()
. Berbeda dengan emplace()
, try_emplace()
tidak mengubah argumennya jika penyisipan gagal karena kunci sudah ada di peta. Misalnya, kode berikut mencoba untuk menempatkan elemen dengan kunci yang sudah disimpan di peta (lihat *):
int main() {
std::map<int, std::unique_ptr<MyClass>> myMap2;
myMap2.emplace(0, std::make_unique<MyClass>(1));
auto pMyObj = std::make_unique<MyClass>(2);
auto [it, b] = myMap2.emplace(0, std::move(pMyObj)); // *
if (!b)
std::cout << "pMyObj was not inserted" << std::endl;
if (pMyObj == nullptr)
std::cout << "pMyObj was modified anyway" << std::endl;
else
std::cout << "pMyObj.m_i = " << pMyObj->m_i << std::endl;
return 0;
}
Output (setidaknya untuk VS2017 dan Coliru):
pMyObj tidak disisipkan
pMyObj tetap dimodifikasi
Seperti yang Anda lihat, pMyObj
tidak lagi menunjuk ke objek aslinya. Namun, jika Anda mengganti auto [it, b] = myMap2.emplace(0, std::move(pMyObj));
dengan kode berikut, maka keluarannya terlihat berbeda, karena pMyObj
tetap tidak berubah:
auto [it, b] = myMap2.try_emplace(0, std::move(pMyObj));
Keluaran:
pMyObj tidak dimasukkan
pMyObj pMyObj.m_i = 2
Kode di Coliru
Harap diperhatikan: Saya mencoba membuat penjelasan saya sesingkat dan sesederhana mungkin agar sesuai dengan jawaban ini. Untuk penjelasan yang lebih tepat dan komprehensif, saya sarankan membaca artikel tentang Fluent C ++ ini .