单行初始化映射中的C++对象

One-line initialize a C++ object in map

本文关键字:C++ 对象 初始化 映射 单行      更新时间:2023-10-16

初始化类并直接分配给unordered_map的正确方法是什么?

#include <string>
#include <unordered_map>
int main() {
std::unordered_map<std::string, Foo> s;
// Foo foo{1};
s["test"] = Foo(1); // this is bad
return 0;
}

福.h

class Foo {
public:
Foo(int x)
: x_(x) {}
private:
int x_;
};

现在我得到

main.cpp:19:4: note: in instantiation of member function 'std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, Foo, std::hash<std::__cxx11::string>, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, Foo> > >::operator[]' requested here
s["test"] = Foo(1);
^
Foo.h:3:5: note: candidate constructor not viable: requires single argument 'x', but no arguments were provided
Foo(int x)
^
Foo.h:1:7: note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided
class Foo {
^
Foo.h:1:7: note: candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided

问题与s["test"] = Foo(1)有关。

当你想使用operator[]时,map中的元素必须是默认可构造的,因为它默认构造给定键的值,当它还没有出现在map中时。要么使Foo默认可构造,要么改用insertemplace

默认可构造Foo

class Foo {
public:
Foo(int x = 0)   // <- can be called without parameters
: x_(x) {}
private:
int x_;
};

s["test"] = Foo(1)将在s["test"]处默认初始化对象,然后从Foo(1)创建的临时Foo对象复制(或移动(分配给它。

这很糟糕,因为Foo没有默认构造函数,因此无法对其进行默认初始化。

你可以使用unordered_mapinsertemplacetry_emplace方法之一来解决这个问题。 例如:

s.try_emplace("test", 1)

这将使用键"test"直接构造一个新的Foos对象,并将1传递给其构造函数。

当你没有默认构造函数时,你需要使用std::map::insertstd::map::emplacestd::map::try_emplace

例如

s.emplace(std::make_pair("test", Foo(1)));

或更简单的形式

s.emplace("test", Foo(1));