将std map存储在map中

39

我需要将std::map作为值存储在std::map中

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

如何向第二个(内部)地图中插入数据?我尝试了以下方法:

someStorage.insert( std::make_pair("key", std::make_pair("key2", "value2")) );

但是这样会抛出很多错误。有什么问题吗?


3
你能否将“throws a lot of errors”这个表述修改得更加具体一些? - EJoshuaS - Stand with Ukraine
5个回答

59

尝试:

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

someStorage["Hi"]["This Is Layer Two"] = "Value";

8
这样做是不必要的昂贵的,因为它创建了一个默认字符串然后将其重新赋值为传入的值。最好的方法是像Dark Falcon所做的那样:https://dev59.com/u2855IYBdhLWcg3wMRVW#4479026。我认为你现在得到的投票只是因为你积累了足够的分数,而不是你回答的质量。我希望人们能花时间阅读/思考你的回答。 - Matthieu N.
23
我喜欢我的答案,因为它最容易阅读。费用很少是一个因素,可维护性才是真正的成本。这段代码是最容易维护的。PS. 复制一个字符串的代价与复制几个整数差不多(因为 大多 数个 std::string 实现采用写时复制方法,因此字符串实际上并没有被复制)。 - Martin York
3
创建一个默认字符串并将 char const* 赋值给它的成本是多少?默认的 std::string 可能不需要进行内存分配(如果您的库提供者需要,请更换),然后有 std::string& std::string::operator=(char const*),当然,如果字符串已经存在,则可以避免构建一个不会被插入的临时 std::string... 我认为你最近有点过于尖刻了。 - Matthieu M.
2
我对这里的争论不是特别感兴趣--但要记住,您上面的回答在语义上与“插入”不等价,因为它将覆盖已经存在的值,而“插入”则不会。当然,最好的选择取决于上下文--但在这种情况下,原始问题似乎确实要求使用“插入”。 - Stuart Golodetz
2
@Gracchus:在C++03中,性能损失最多也是微不足道的。使用C++11和移动语义,它甚至更不相关了。现在你需要考虑的是是否使用std::mapstd::unordered_map - Martin York
显示剩余4条评论

29
someStorage["key"].insert(std::make_pair("key2", "value2")));

如果你仍然想在外部地图上使用insert方法,这是一种方法:

std::map<std::string, std::string> inner;
inner.insert(std::make_pair("key2", "value2"));
someStorage.insert(std::make_pair("key", inner));

2
你知道吗,如果需要的话,someStorage["key"] 会进行插入,并使用默认初始化值吗?换句话说,如果该键不存在,则会将一个空映射与该键关联。 - Dark Falcon
3
不应使用make_pair。假设实现使用pair是错误的。使用std::map<Key, Value>::value_type,它特别为此目的typedefed。 - Martin York
2
相反地:C++0x标准表示:“对于map<Key,T>,key_type是Key,value_type是pair<const Key,T>。”(23.4.1.2) - Dark Falcon
1
@Martin:他引用的那一部分本质上是标准中一个具体的保证,即这两者是等价的。换句话说,在这里始终保证make_pair能够正常工作(就我个人经验而言,在进行insert时,这也是惯用法)。 - Stuart Golodetz
1
@Stuart Golodetz: @Dark Falcon: 是的,我明白了。但是你认为make_pair返回的类型是什么?提示一下,它不同于value_type,因为"key1"、"key2"和"value2"不是std::strings!你正在侥幸地进行一些隐式转换。使用value_type,您可以获得正确的类型,而无需担心编译器进行任何隐式转换。在我的团队(可能是整个公司):在代码审查时会删除make_pair。这里idiomatic的是value_type(因为它是存储在map中的类型)。 - Martin York
显示剩余11条评论

4

一个地图有一个插入方法,接受一个键值对。你的键是字符串类型,所以没问题,但你的值不是一对(你生成的),而是一个地图类型。所以你需要将一个完整的地图存储为你的值,或者改变初始地图定义来接受一对作为值。


4

//试一下这个:

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

myMap["key one"]["Key Two"] = "Value";
myMap["Hello"]["my name is"] = "Value";

//打印地图:

for( map<string,map<string,string> >::const_iterator ptr=myMap.begin();ptr!=myMap.end(); ptr++) {
    cout << ptr->first << "\n";
    for( map<string,string>::const_iterator eptr=ptr->second.begin();eptr!=ptr->second.end(); eptr++){
        cout << eptr->first << " " << eptr->second << endl;

    }

}

2
此外,您还可以使用列表初始化:
someStorage.insert( std::make_pair("key", std::map<std::string, std::string> {std::make_pair("key2", "value2")}) );

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接