英文:
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);
}
我还认为可以使用insert
、insert_or_assign
、emplace
、emplace_hint
、try_emplace
来实现。我对所有这些可能性有点困惑...
我对C++11或C++17的解决方案感兴趣。
英文:
I have instances of std::map<std::string,Foo>
where I insert and fill data. The class Foo
is default-constructible, default-copyable. Then I do it by this (simple) way:
std::map<std::string,Foo> data;
for(std::string const& key : keys)
{
assert(data.count(key) == 0); // it's assumed that the keys not already exist
Foo& 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<std::string,Foo> data;
for(std::string const& key : keys)
{
assert(data.count(key) == 0); // it's assumed that the keys not already exist
Foo& foo = data.emplace(key, Foo(requirement)).first->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::emplace
与std::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 <map>
#include <string>
#include <iostream>
struct Foo
{
Foo(int n) : m_n(n) {}
int m_n;
};
int main()
{
std::map<std::string, Foo> m;
// Create a Foo and insert it:
Foo foo{ 111 };
// foo.fill(blahblah);
m.emplace("aaa", std::move(foo));
// Verify it was inserted properly:
Foo& foo2 = m.at("aaa");
std::cout << foo2.m_n << std::endl;
return 0;
}
Output:
111
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->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->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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论