简体   繁体   English

将空向量放入std :: map()

[英]Emplace empty vector into std::map()

How can I emplace an empty vector into a std::map ? 如何将空向量放置到std::map For example, if I have a std::map<int, std::vector<int>> , and I want map[4] to contain an empty std::vector<int> , what can I call? 例如,如果我有一个std::map<int, std::vector<int>> ,并且我想要map[4]包含一个空的std::vector<int> ,那我该怎么称呼?

If you use operator[](const Key&) , the map will automatically emplace a value-initialized (ie in the case of std::vector , default-constructed ) value if you access an element that does not exist. 如果使用operator[](const Key&) ,则当您访问不存在的元素时,映射将自动放置一个值初始化 (例如,在std::vector的情况下为default-constructed )。 See here: 看这里:

http://en.cppreference.com/w/cpp/container/map/operator_at http://en.cppreference.com/w/cpp/container/map/operator_at

(Since C++ 11 the details are a tad more complicated, but in your case this is what matters). (由于C ++ 11,细节有些复杂,但是在您的情况下,这很重要)。

That means if your map is empty and you do map[4] , it will readily give you a reference to an empty (default-constructed) vector. 这意味着,如果您的地图是空的,并且您执行map[4] ,它将很容易为您提供对空(默认构造)矢量的引用。 Assigning an empty vector is unnecessary, although it may make your intent more clear. 尽管可以使您的意图更加清楚,但不必分配空向量。

Demo: https://godbolt.org/g/rnfW7g 演示: https//godbolt.org/g/rnfW7g

Unfortunately the strictly-correct answer is indeed to use std::piecewise_construct as the first argument, followed by two tuples. 不幸的是,严格正确的答案的确是使用std::piecewise_construct作为第一个参数,然后是两个元组。 The first represents the arguments to create the key (4), and the second represents the arguments to create the vector (empty argument set). 第一个代表创建键(4)的参数,第二个代表创建向量的参数(空参数集)。

It would look like this: 它看起来像这样:

map.emplace(std::piecewise_construct,   // signal piecewise construction
            std::make_tuple(4),         // key constructed from int(4)
            std::make_tuple());         // value is default constructed

Of course this looks unsightly, and other alternatives will work. 当然,这看起来很难看,其他替代方法也可以使用。 They may even generate no more code in an optimised build: 他们甚至可以在优化的版本中不再生成任何代码:

This one notionally invokes default-construction and move-assignment, but it is likely that the optimiser will see through it. 从概念上讲,此调用了默认构造和移动分配,但优化器很可能会看到它。

map.emplace(4, std::vector<int>());

This one invokes default-construction followed by copy-assignment. 这将调用默认构造,然后是复制分配。 But again, the optimiser may well see through it. 但同样,优化器可能会完全了解它。

map[4] = {};

To ensure an empty vector is placed at position 4, you may simply attempt to clear the vector at position 4. 为了确保将空矢量放置在位置4上,您可以简单地尝试clear位置4上的矢量。

std::map<int, std::vector<int>> my_map;
my_map[4].clear();

As others have mentioned, the indexing operator for std::map will construct an empty value at the specified index if none already exists. 正如其他人提到的那样,如果std::map的索引运算符不存在,则它将在指定的索引处构造一个空值。 If that is the case, calling clear is redundant. 在这种情况下,调用clear是多余的。 However, if a std::vector<int> does already exist, the call to clear serves to, well, clear the vector there, resulting in an empty vector. 但是,如果std::vector<int>已经存在,则调用clear可以清除那里的向量,从而导致一个空向量。

This may be more efficient than my previous approach of assigning to {} (see below), because we probably plan on adding elements to the vector at position 4, and we don't pay any cost of new allocation this way. 这可能比我以前分配给{}方法更有效(请参阅下文),因为我们可能计划在位置4的向量上添加元素,并且我们不为此付出任何新分配的费用。 Additionally, if previous usage of my_map[4] indicates future usage, then our new vector will likely be eventually resized to the nearly the same size as before, meaning we save on reallocation costs. 另外,如果my_map[4]先前用法表示将来的用法,那么我们的新向量最终可能会被调整为与以前几乎相同的大小,这意味着我们节省了重新分配的成本。


Previous approach: 以前的方法:

just assign to {} and the container should properly construct an empty vector there: 只需分配给{} ,容器就应该在那里正确构造一个空向量:

std::map<int, std::vector<int>> my_map;
my_map[4] = {};
std::cout << my_map.size() << std::endl; // prints 1

Demo 演示版

Edit: As Jodocus mentions, if you know that the std::map doesn't already contain a vector at position 4, then simply attempting to access the vector at that position will default-construct one, eg: 编辑:如Jodocus所述,如果您知道std::map在位置4处尚未包含vector ,则仅尝试访问该位置处的向量将默认构造一个,例如:

std::map<int, std::vector<int>> my_map;
my_map[4]; // default-constructs a vector there

What's wrong with the simplest possible solution? 最简单的解决方案怎么了? std::map[4] = {}; .

In modern C++, this should do what you want with no or at least, very little, overhead. 在现代C ++中,这应该没有任何开销,或者至少很少有开销。

If you must use emplace , the best solution I can come up with is this: 如果必须使用emplace ,我能想到的最好的解决方案是:

std::map<int, std::vector<int>> map;
map.emplace(4, std::vector<int>());

Use piecewise_construct with std::make_tuple: 将piecewise_construct与std :: make_tuple一起使用:

map.emplace(std::piecewise_construct, std::make_tuple(4), std::make_tuple());

We are inserting an empty vector at position 4. 我们在位置4插入一个空向量。

And if there is a general case like, emplacing a vector of size 100 with 10 filled up then: 如果有一般情况,将大小为100的向量填充为10,则:

map.emplace(std::piecewise_construct, std::make_tuple(4), std::make_tuple(100, 10));

piecewise_construct : This constant value is passed as the first argument to construct a pair object to select the constructor form that constructs its members in place by forwarding the elements of two tuple objects to their respective constructor. piecewise_construct :此常量值作为构造对对象的第一个参数传递,以选择构造函数形式,该形式通过将两个元组对象的元素转发到各自的构造函数来就地构造其成员。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM