std :: map:当元素不是默认可构造的时,创建/替换元素

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

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),并且如果键已经存在,则所有这些方法都不起作用。

HAHA362 回答:std :: map:当元素不是默认可构造的时,创建/替换元素

我已经查看了常见的地图方法(插入,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));

full program demo

本文链接:https://www.f2er.com/2763151.html

大家都在问