C++编译错误:为何unordered_map需要item类的默认构造函数?
问题解答:为什么这里需要默认构造函数?
你的怀疑没错,问题确实出在blah["armor"]这类std::unordered_map的operator[]调用上。
核心原因:operator[]的行为逻辑
std::unordered_map(包括std::map)的operator[]有个特殊行为:当你通过键访问元素时,如果这个键不存在于容器中,它会自动执行两个操作:
- 用默认构造函数创建一个对应值类型的对象(也就是你的
item对象) - 将这个新对象插入到map中,然后返回它的引用
而你的item结构体因为自定义了带参数的构造函数,编译器不会自动生成默认构造函数,你又把显式声明的item() = default;注释掉了,导致operator[]需要调用默认构造函数时找不到匹配的函数,直接报错。
代码里的触发点
你代码里有两处会触发这个逻辑:
createItems函数里的blah["armor"] = i1;:第一次用"armor"作为键调用operator[]时,键不存在,会尝试默认构造item,之后再把i1赋值给这个新对象。main函数里的cout << blah["armor"].name...:虽然这里"armor"已经被插入,但operator[]的设计本身就要求值类型必须支持默认构造——哪怕实际运行时不会触发,编译器也会强制检查这个要求。
解决办法
你可以选以下任意一种方式修复:
- 恢复默认构造函数:取消注释
item() = default;,让编译器生成默认构造的item对象。 - 改用
insert/emplace插入元素:替换operator[]赋值的方式,比如:
这两种方式都是直接构造// 使用insert blah.insert(std::make_pair("armor", i1)); // 或者直接emplace,避免拷贝 blah.emplace("armor", "armor", 1000);item对象并插入,不需要默认构造函数。 - 用
find访问元素:如果只是想访问已存在的元素,不想自动插入新对象,用find方法:auto it = blah.find("armor"); if (it != blah.end()) { cout << it->second.name << " " << it->second.price << endl; }
内容的提问来源于stack exchange,提问作者Nicholas Humphrey
相关产品推荐
相关产品推荐

