map 插入元素的若干种方法
1. insert
尝试插入一个元素。如果 key 已经存在,则插入失败,保持现有值不变
std::pair,包含一个指向元素的迭代器和一个布尔值
1) 布尔值表示是否插入成功
2) 如果布尔值为 true, 迭代器则指向刚插入的元素
3) 如果布尔值为 false, 表示插入失败, 迭代器则指向原有的相同 key 的元素
特点: 不会覆盖现有元素
2. operator[]
如果 key 不存在, 则创建一个新元素, 并将其初始化为 T() (即类型的默认构造值)
返回元素的引用
特点: 快速方便访问值/修改值, 需要注意的是, 如果访问不存在的值, 会隐式创建默认值(使用者可能只想访问元素)
3. emplace
原地构造元素,避免不必要的拷贝或移动
返回值与 `insert` 相同
特点: 构造时效率更高,避免了临时对象的创建, 当已经有一个完全构造好的对象, 应该使用`insert`更合适; `emplace` 适合构造对象并插入的场景
4. insert_or_assign (C++17 引入)
作用: 如果 key 不存在,则插入;如果存在,则覆盖现有值
返回值: std::pair,包含一个迭代器和一个布尔值,表示是否是新插入
特点: 相比 insert,允许更新已存在的值, 简化插入更新操作, 值得注意的是: 如果 key 存在,insert_or_assign 会强制更新值,即使新值和旧值相同,这可能带来额外的构造或赋值操作
5. try_emplace (C++17 引入)
作用: 如果 key 不存在,则原地构造并插入;如果存在,不修改现有值
返回值: 与 insert 相同
特点: 类似于 `emplace`,大多数情况下可以替换掉 `emplace`, 但当 `map` 使用的是不可复制且不可移动的 `key` 类型,那么 `try_emplace` 会报错,因为它需要复制或移动 key
#include <map>
#include <string>
class NonCopyableNonMovableKey {
public:
NonCopyableNonMovableKey(int id) : id_(id) {}
NonCopyableNonMovableKey(const NonCopyableNonMovableKey&) = delete;
NonCopyableNonMovableKey& operator=(const NonCopyableNonMovableKey&) = delete;
NonCopyableNonMovableKey(NonCopyableNonMovableKey&&) = delete;
NonCopyableNonMovableKey& operator=(NonCopyableNonMovableKey&&) = delete;
int getId() const { return id_; }
bool operator<(const NonCopyableNonMovableKey& other) const {
return id_ < other.id_;
}
private:
int id_;
};
int main() {
std::map<NonCopyableNonMovableKey, std::string> myMap;
myMap.emplace(1, "b");
// myMap.try_emplace(1, "b"); // C2280
return 0;
}