【问题标题】:std::map: Creating/replacing an element when it is not default-constructiblestd::map:当元素不可默认构造时创建/替换元素
【发布时间】:2020-05-02 13:32:53
【问题描述】:

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

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++)预期的方式吗?我觉得这是不对的;作为一名程序员,我不想为这么少的东西写这么多的代码。但似乎没有简单的出路:我查找了常见的 map 方法(insert、emplace、emplace_hint),如果密钥已经存在,它们都什么都不做。

【问题讨论】:

  • 通常,如果您发现代码过多,您可以通过将其设为函数来解决问题。突然之间,需要写太多行的任务可以在一行中完成。
  • 是的。但我相信这是一项非常常见的任务,所以我假设 C++ 委员会(或设计该语言的人)对此有解决方案。
  • @buj: "我相信这是一个很常见的任务" 这就是问题所在。 C++ 作为一种语言和标准库,通常不喜欢当类型不可默认构造时。可以创建和使用此类类型,但从广义上讲,您在通用 C++ 代码中使用此类类型的能力将受到限制。

标签: c++ std stdmap deleted-functions


【解决方案1】:

我查找了常见的映射方法(insert、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&lt;M&gt;(obj)分配给与键k对应的mapped_type。如果键不存在,则插入新值,就像通过插入一样,从value_type(k, std::forward&lt;M&gt;(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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-28
    • 1970-01-01
    • 1970-01-01
    • 2018-10-04
    • 2022-01-24
    相关资源
    最近更新 更多