c++ 如何在std::map中嵌入无参数构造函数的对象?

bbuxkriu  于 2023-04-23  发布在  其他
关注(0)|答案(6)|浏览(195)

我想把一个对象放到一个std::map中,这个std::map的构造函数不接受任何参数。但是,std::map::emplace似乎除了键之外还需要至少一个额外的参数。那么我怎么才能把零个参数转发给构造函数呢?

rqenqsqc

rqenqsqc1#

std::map<K, V>的元素类型实际上是std::pair<K, V>,所以当你在map中嵌入时,参数会被转发到std::pair的构造函数。这就是为什么你不能只传递key:std::pair<K, V>不能由单个参数构造(除非它是另一对相同类型的参数)。您可以传递零个参数,但随后键将被值初始化,这可能不是您想要的。
在大多数情况下,移动值的成本很低(键也很小,可以复制),你真的应该这样做:

M.emplace(k, V{});

其中V是Map类型。它将被初始化并移动到容器中。(移动甚至可能被省略;我不确定。)
如果你不能移动,你真的需要V被就地构造,你必须使用分段构造构造器。

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

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

8yparm6h

8yparm6h2#

您可以显式创建一个pair并将其传递给map::emplace,或者使用std::pairpiecewise construction constructor

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

Live demo

qco9c6ql

qco9c6ql3#

当我创建一个std::mutex对象的std::map时也遇到了同样的问题,问题是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
}
tvz2xvvm

tvz2xvvm4#

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

#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

2nbm6dog

2nbm6dog5#

#include <iostream>
#include <unordered_map>

using namespace std;

class A
{
public:
    A()
    {
        cout << "A ctor\n";
    }

    A(int arg)
    {
        cout << "A ctor2\n";
    }

    A(const char* arg)
    {
        cout << "A ctor3\n";
    }

    A(int j, const char* arg)
    {
        cout << "A ctor4\n";
    }

    A(const A& a)
    {
        cout << "A copy ctor\n";
    }

    ~A()
    {
        cout << "A dtor\n";
    }
};

int main()
{
    unordered_map<int, A> map;

    map.emplace(std::piecewise_construct, std::forward_as_tuple(2), std::forward_as_tuple(2, "ups"));
}

打印输出

A ctor4
A dtor
iqxoj9l9

iqxoj9l96#

Class ToolMap() 
{
 friend class std::map;
  public (std::map)Object ToolMap()
  {
     return Object;
  }

}

相关问题