2

假设您有一个不可默认构造的类。

class A {
  private:
    int a;
  public:
    A() = delete;
    A(int a0) : a(a0) {}
};

现在,我们有一些映射 Int --> A, std::map<int, A> mapping。假设我们要为某个键 0 创建一个新映射,如果该键存在,我们要替换旧值。对默认可构造类执行此操作的方法是:

mapping[0] = A(4);

然而,对于 A 类,这将失败,因为 operator[] 首先构造了 A 的默认实例,然后才会分配 的值A(4)。通常这样做的一种方法(即对于非默认可构造类)是这样的:

auto it = mapping.find(0);
if (it == mapping.end()) {
  mapping.insert(0, A(4));
}
else {
  it->second = A(4);
}

我的问题是:这真的是(C++)预期的方式吗?我觉得这是不对的;作为一名程序员,我不想为这么少的东西编写这么多的代码。但似乎没有简单的出路:我查找了常见的映射方法(插入、emplace、emplace_hint),如果密钥已经存在,它们都什么都不做。

4

1 回答 1

5

我查找了常见的映射方法(插入、emplace、emplace_hint),如果密钥已经存在,它们都什么都不做。

C++17 已经解决了这一点std::map::insert_or_assign

template <class M>
pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);

k如果容器中已经存在等效的键,则分配给与std::forward<M>(obj)mapped_type对应的键k。如果键不存在,则插入新值,就像通过插入一样,从value_type(k, std::forward<M>(obj)) 构造它。

这使得

auto it = mapping.find(0);
if (it == mapping.end()) {
  mapping.insert(0, A(4));
}
else {
  it->second = A(4);
}

好像

mapping.insert_or_assign(0, A(4));

完整程序演示

于 2020-01-15T18:18:29.473 回答