如何使用无参数构造函数将对象置于std :: map中?

Ink*_*ane 55 c++ c++11

我想将一个对象置于std::map其构造函数不带任何参数的对象中.但是,std::map::emplace除了密钥之外,似乎还需要至少一个额外的参数.那么如何将零参数转发给构造函数呢?

Bri*_*ian 53

元素类型std::map<K, V>实际上是std::pair<K, V>,所以当你进入地图时,参数将被转发给构造函数std::pair.这就是为什么你不能只传递密钥:std::pair<K, V>不能用单个参数构造(除非它是另一对相同的类型.)你可以传递零参数,但是密钥将被初始化,这可能是不是你想要的.

在大多数情况下,移动值将很便宜(并且键很小并且可以复制),你应该真的只做这样的事情:

M.emplace(k, V{});
Run Code Online (Sandbox Code Playgroud)

V映射类型在哪里.它将被初始化并移动到容器中.(此举甚至可能被忽略;我不确定.)

如果你不能移动,并且你真的需要V就地构建,你必须使用分段构造构造函数......

M.emplace(std::piecewise_construct, std::make_tuple(k), std::make_tuple());
Run Code Online (Sandbox Code Playgroud)

这导致使用零参数(值初始化)std::pair构造第一个元素k和第二个元素.

  • 注意,一个简单的`M [k];`将具有与`piecewise_construct` malarkey相同的效果. (12认同)
  • M [k]返回参考;有时获取迭代器会很有用。 (2认同)

Pra*_*ian 17

你可以明确地创建pair并传递至map::emplace,或使用分段施工构造std::pair.

struct foo {};

std::map<int, foo> m;

m.emplace(std::pair<int, foo>(1, {}));
m.emplace(std::piecewise_construct,
          std::forward_as_tuple(2),
          std::forward_as_tuple());
Run Code Online (Sandbox Code Playgroud)

现场演示


Rom*_*lov 9

我有同样的问题,当我不得不创建std::mapstd::mutex对象.问题是std::mutex既不可复制也不可移动,所以我需要"就地"构建它.

接受的答案对于这种情况不起作用(M.emplace(k, V{});需要V可以移动).而且我不想使用复杂且不太可读的std::piecewise_construct选项(参见上面的其他答案).

我的解决方案更简单 - 只需使用operator[]- 它将使用其默认构造函数创建值并返回对它的引用.或者它只是找到并返回对现有项目的引用,而不创建新项目.

std::map<std::string, std::mutex> map;

std::mutex& GetMutexForFile(const std::string& filename)
{
    return map[filename]; // constructs it inside the map if doesn't exist
}
Run Code Online (Sandbox Code Playgroud)

  • @Keith M最初的问题是关于默认构造函数. (2认同)

Dev*_*ull 7

在C ++ 17中,您可以使用std::map::try_emplace,它在std::piecewise_construct内部使用,看起来并不那么麻烦。它还将键作为第一个参数(而不是std::pair::pair()像将所有内容一样转发emplace)。

#include <map>

struct A {
    A() = default;
};

int main()
{
    std::map<int, A> map;

    map.emplace(std::piecewise_construct,
                std::forward_as_tuple(10),
                std::forward_as_tuple());
    // ...vs...
    map.try_emplace(10);
}
Run Code Online (Sandbox Code Playgroud)

现场例子

  • 是的,“try_emplace()”几乎就是“emplace()”应该有的样子。 (2认同)