Оскільки C ++ 17 std::map пропонує два нові способи вставки: insert_or_assign()і try_emplace(), як також згадується у коментарі sp2danny .
insert_or_assign()
В основному, insert_or_assign()це "вдосконалена" версія operator[]. На відміну від цього operator[], insert_or_assign()не вимагає, щоб тип значення карти був конструктованим за замовчуванням. Наприклад, наступний код не компілюється, оскільки MyClassне має конструктора за замовчуванням:
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;
}
Однак якщо ви заміните myMap[0] = MyClass(1);наступний рядок, код збирається, а вставка відбувається за призначенням:
myMap.insert_or_assign(0, MyClass(1));
Більше того, подібний до insert(), insert_or_assign()повертає a pair<iterator, bool>. Булеве значення - це trueякщо вставка і falseякщо було виконано призначення. Ітератор вказує на елемент, який був вставлений або оновлений.
try_emplace()
Подібним до вищесказаного try_emplace()є "поліпшення" emplace(). На відміну від emplace(), try_emplace()не змінює своїх аргументів, якщо вставка не вдається через ключ, який вже існує на карті. Наприклад, наступний код намагається замінити елемент ключем, який вже зберігається на карті (див. *):
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;
}
Вихід (принаймні для VS2017 та Coliru):
pMyObj не було вставлено
pMyObj було змінено
Як бачите, pMyObjбільше не вказує на оригінальний об’єкт. Однак якщо замінити auto [it, b] = myMap2.emplace(0, std::move(pMyObj));наступним кодом, то результат виглядає інакше, оскільки pMyObjзалишається незмінним:
auto [it, b] = myMap2.try_emplace(0, std::move(pMyObj));
Вихід:
pMyObj не було вставлено
pMyObj pMyObj.m_i = 2
Код про Коліру
Зверніть увагу: я намагався зробити свої пояснення максимально короткими та простими, щоб вписати їх у цю відповідь. Для більш точного та вичерпного опису рекомендую прочитати цю статтю на Fluent C ++ .