如何用迭代器初始化map的key字段?为何it->first赋值失败而second可行?
嘿,我来帮你搞清楚这两个和std::map迭代器相关的问题~
1. 如何使用迭代器初始化map的key字段?
首先得明确:std::map的key是不可修改的——因为map是基于key有序排列的,如果允许修改key,会直接破坏map的内部有序结构。所以你没法直接通过迭代器去修改已存在元素的key。
如果要初始化map的key,正确的方式是在插入元素的时候就指定好key,常见的实现方法有这些:
- 使用
insert()方法插入键值对:
std::map<std::string, std::string> mapa; // 插入一个key为"first_key",value为"first_val"的元素 mapa.insert(std::make_pair("first_key", "first_val"));
- 使用
emplace()方法(更高效,直接在map内部构造元素):
// 直接构造key为"second_key",value为"second_val"的元素 auto it = mapa.emplace("second_key", "second_val").first; // 这里的it就是指向新插入元素的迭代器,可用来操作value
- 使用
[]操作符(如果key不存在会自动插入,存在则返回对应value的引用):
// 插入key为"third_key"的元素,value初始化为空字符串后赋值 mapa["third_key"] = "third_val";
如果真的需要修改某个元素的key,本质上只能先删除旧元素,再插入一个新key、同value的元素,示例:
// 假设it是指向旧元素的有效迭代器 std::string old_key = it->first; std::string val = it->second; mapa.erase(it); // 删除旧元素 mapa.emplace(new_key, val); // 插入新key的元素
2. 你的代码里为什么it->first = s不生效,但it->second可以?
你的代码存在两个关键问题:
问题一:迭代器指向空map的尾后位置
当std::map<std::string,std::string> mapa;初始化后,map是空的,此时mapa.begin()等于mapa.end()——这是一个尾后迭代器,不能被解引用(也就是不能用it->first或it->second),这种操作属于未定义行为,运行时可能崩溃或者出现奇怪的结果。
问题二:std::map的key是const类型
就算你的map里有元素,迭代器指向的元素类型是std::pair<const std::string, std::string>——注意first成员是const的!这是map的特性,保证key不能被修改,否则会打乱map的有序结构。所以it->first = s这种写法本质上是试图修改const对象,正常情况下编译器应该直接报错阻止你这么做。
而it->second可以正常赋值,是因为pair的second成员是非const的,map允许你修改元素的value,这不会影响map的有序性。
修正后的示例代码
这里给你改了一下代码,展示正确的用法:
#include <iostream> #include <map> #include <string> int main () { std::string s; std::cout<<" String : "; std::getline(std::cin,s); std::map<std::string,std::string> mapa; // 先插入一个元素,获取指向它的迭代器 auto it = mapa.emplace("temp_key", "").first; // 可以正常修改value it->second = s; std::cout << "修改后的value:" << it->second << std::endl; // 如果要把key改成输入的s,需要先删再插 std::string val = it->second; mapa.erase(it); auto new_it = mapa.emplace(s, val).first; std::cout << "新元素的key:" << new_it->first << ",value:" << new_it->second << std::endl; return 0; }
内容的提问来源于stack exchange,提问作者Dinno Koluh

