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

时间:2014-12-18 18:59:29

标签: c++ c++11

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

5 个答案:

答案 0 :(得分:43)

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

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

M.emplace(k, V{});

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

如果您无法移动,并且您确实需要就地构建V,则必须使用分段构造构造函数...

M.emplace(std::piecewise_construct, std::make_tuple(k), std::make_tuple());

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

答案 1 :(得分:16)

您可以明确创建pair并将其传递给map::emplace,或使用std::pair的{​​{3}}。

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());

piecewise construction constructor

答案 2 :(得分: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
}

答案 3 :(得分:3)

在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);
}

Live example

答案 4 :(得分:-2)

dirs[:] = [dir for dir in dirs if not (
           re.search(r'\bEXP\b', dir) or
           re.search(r'\b3.2\b', dir) or
           re.search(r'\w+(?:-\w+)+', dir))]