在std::map中插入时,没有默认的空构造函数。

huangapple go评论70阅读模式
英文:

Insert in std::map without default empty constructor

问题

我有std::map<std::string, Foo>的实例,我在其中插入并填充数据。类Foo具有默认构造函数和默认可复制构造函数。然后,我通过以下(简单)方法来执行:

std::map<std::string, Foo> data;
for (const std::string& key : keys)
{
  assert(data.count(key) == 0); // 假设键不存在
  Foo& foo = data[key];
  foo.fill(blahblah);
}

重构后,类Foo丢失了默认的空构造函数。有哪些(简单)替代方法来插入和填充data 目前,我用以下方式替代,但我不知道是否是重构代码的最佳/最简单方式:

std::map<std::string, Foo> data;
for (const std::string& key : keys)
{
  assert(data.count(key) == 0); // 假设键不存在
  Foo& foo = data.emplace(key, Foo(requirement)).first->second;
  foo.fill(blahblah);
}

我还认为可以使用insertinsert_or_assignemplaceemplace_hinttry_emplace来实现。我对所有这些可能性有点困惑...

我对C++11或C++17的解决方案感兴趣。

英文:

I have instances of std::map&lt;std::string,Foo&gt; where I insert and fill data. The class Foo is default-constructible, default-copyable. Then I do it by this (simple) way:

std::map&lt;std::string,Foo&gt; data;
for(std::string const&amp; key : keys)
{
  assert(data.count(key) == 0); // it&#39;s assumed that the keys not already exist
  Foo&amp; foo = data[key];
  foo.fill(blahblah);
}

After refactoring, the class Foo lost the default empty constructor. What are the (simple) alternatives to insert and fill data ? For the moment, I replaced by this but I don't know if it's the best/simplier way to refactor the code:

std::map&lt;std::string,Foo&gt; data;
for(std::string const&amp; key : keys)
{
  assert(data.count(key) == 0); // it&#39;s assumed that the keys not already exist
  Foo&amp; foo = data.emplace(key, Foo(requirement)).first-&gt;second;
  foo.fill(blahblah);
}

I also think it could be possible with insert, insert_or_assign, emplace, emplace_hint, try_emplace. I'm a little bit lost with all the possibilities...

I'm interested in solutions for C++11 or C++17.

答案1

得分: 2

以下是您要翻译的内容:

可以使用std::map::emplacestd::move一起添加一个没有默认构造函数的类的元素。这可以在使用fill(...)初始化之后完成。

示例:

#include <map>
#include <string>
#include <iostream>

struct Foo
{
    Foo(int n) : m_n(n) {}
    int m_n;
};

int main() 
{
    std::map<std::string, Foo> m;

    // 创建一个Foo并插入它:
    Foo foo{ 111 };
    // foo.fill(blahblah);
    m.emplace("aaa", std::move(foo));

    // 验证它是否已正确插入:
    Foo& foo2 = m.at("aaa");
    std::cout << foo2.m_n << std::endl;
    return 0;
}

输出:

111

在线演示

请注意,我使用std::map::at来验证元素是否已正确插入(使用operator[]将因Foo缺少默认构造函数而无法编译通过)。

英文:

You can use std::map::emplace together with std::move in order to add an element of a class that lacks a default constructor. This can be done after it was initialized with fill(...).

Example:

#include &lt;map&gt;
#include &lt;string&gt;
#include &lt;iostream&gt;

struct Foo
{
    Foo(int n) : m_n(n) {}
    int m_n;
};

int main() 
{
    std::map&lt;std::string, Foo&gt; m;

    // Create a Foo and insert it:
    Foo foo{ 111 };
    // foo.fill(blahblah);
    m.emplace(&quot;aaa&quot;, std::move(foo));

    // Verify it was inserted properly:
    Foo&amp; foo2 = m.at(&quot;aaa&quot;);
    std::cout &lt;&lt; foo2.m_n &lt;&lt; std::endl;
    return 0;
}

Output:

111

Live demo

Note that I used std::map::at to verify that the element was inserted properly (using operator[] will fail to compile due to Foo lacking a default ctor).

答案2

得分: 2

我会简单地选择:

data.emplace(key, requirement)

或者,自从C++17以来,使用

data.try_emplace(key, requirement)

使用 try_emplace 通常更好(请参考其他答案中提到的问题); 但是,据我所知,在你的情况下,这两个选项实际上是相同的。

英文:

I would simply go with:

data.emplace(key, requirement)

or, since C++17, with

data.try_emplace(key, requirement)

Using try_emplace is generally better (see the question mentioned in the other answer); however, ASAIK, in your case, both options are effectively the same.

答案3

得分: 1

From here

> A call to this function is equivalent to:
>
> (*((this-&gt;insert(make_pair(k,mapped_type()))).first)).

So the literal replacement for the operator[] in this case would be using the insert function. However, I would suggest using emplace in order to avoid additional construction of std::pair, which the insert function accepts as an argument.

Since C++17, you can use try_emplace except in very subtle cases. You can refer to this discussion in order to see if preferring emplace over try_emplace applies to your case.

英文:

From here

> A call to this function is equivalent to:
>
> (*((this-&gt;insert(make_pair(k,mapped_type()))).first)).

So the literal replacement for the operator[] in this case would be using insert function. However, I would suggest using emplace in order to avoid additional construction of std::pair, which insert function accepts as argument.

Since C++17, you can use try_emplace except very subtle cases. You can refer to this discussion in order to see if preferring emplace over try_emplace applies to you case.

huangapple
  • 本文由 发表于 2023年4月13日 19:52:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/76005097.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定