将std :: vector复制到boost :: unordered_map <string,std :: vector <foo =“”>&gt; </string,>

时间:2013-12-23 05:00:40

标签: boost c++11 vector unordered-map

将记录类型映射到字段值向量:

unordered_map<string, vector<string>> input_records;
string rec_type {"name"};
vector<string> fields { "field 1", "field 2", "field 3" };

我想将fields复制到input_records[rec_type]。以下工作:

_input_records[rec_type].insert(rec_deq.begin(), rec_deq.end()); 

然而,unordered_map的boost文档包含:

template<typename InputIterator> 
void insert(InputIterator first, InputIterator last);

Inserts a range of elements into the container. Elements are inserted if and only if there is no element in the container with an equivalent key.

Throws:
When inserting a single element, if an exception is thrown by an operation other than a call to hasher the function has no effect.
Notes:
Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.
Pointers and references to elements are never invalidated.

(写这个,我意识到InputIterator可能指向一系列键/值对,每个键都要插入到Map中。所以,错误的方法。)

如何最好地在input_record[rec_type]实例化和填充向量?填充后,矢量将不会被修改。它是否像input_record[rec_type] = fields一样简单?在这种情况下,是否可以“移动语义”?

1 个答案:

答案 0 :(得分:1)

在标准关联容器中,你推入的是std :: pair,大部分时间使用std :: make_pair()。

#include <vector>
#include <string>
#include <unordered_map>
#include <iostream>

using namespace std;

int main()
{
    unordered_map<string, vector<string>> input_records;
    string rec_type {"name"};
    vector<string> fields { "field 1", "field 2", "field 3" };   

    input_records.insert( make_pair( rec_type, fields ) );

    for( const auto& text : input_records[rec_type] )
        cout << text << '\n';
}

对于Boost容器也是如此,因为它们基于标准容器。

此外,由于C ++ 11还有另一个函数emplace(),它允许你创建一个“就地”一对而不必先构建它然后将它传递给容器:

#include <vector>
#include <string>
#include <unordered_map>
#include <iostream>

using namespace std;

int main()
{
    unordered_map<string, vector<string>> input_records;
    string rec_type {"name"};
    vector<string> fields { "field 1", "field 2", "field 3" };   

    input_records.emplace( rec_type, fields );

    for( const auto& text : input_records[rec_type] )
        cout << text << '\n';
}

根据您传递数据的方式(右值参考?移动?等),会有更多或更少的副本。但是,一个适用于所有标准容器的简单经验法则是,您应该尝试使用emplace(),直到您处于必须使用insert()的情况。

使用input_record[rec_type]可以正常工作。但是,我建议使用find(),因为[]运算符将添加一个新元素,如果找不到,whild find()将返回一个迭代器,如果它不是container.end()找到元素,所以你只需将迭代器与end()进行比较,就可以知道元素是否被找到。 对于所有标准关联容器和增强容器都是如此。

大多数时候我使用关联容器封装到一个代表我想要的概念的类中:就像一个InputRecord类。然后我提供一个find函数(或任何适合该域的动作名称),它完全符合我的要求,具体取决于具体情况:有时我希望它在未找到对象时抛出异常,有时我想创建当我找到的那个不存在的新记录时,有时我想返回一个指针,有时我更喜欢返回一个boost :: optional。

你最好做同样的事情:将你的概念封装在一个类下,公开所需的服务,然后使用你想要的任何东西,无论你想要在类中。如果您以后需要更改接口,只需更改操作容器的类中的代码即可轻松切换到另一个容器。