Qt C++中QMap().begin()函数的非直观行为探究
为什么QMap会自动创建不存在的元素?
先看一下你提供的示例代码:
#include <QMap> #include <QDebug> int main() { QMap<int, QMap<int, int>> testA; testA [0][0] = 1; QMap<int,int>::iterator _iterTestA; for(_iterTestA = testA[1].begin(); _iterTestA!= testA[1].end(); _iterTestA++){ qDebug()<<"Why am I working!? "; } qDebug()<<" testA " << testA; }
你预期代码会因为访问不存在的testA[1]而抛出错误,但实际Qt自动创建了一个空的QMap<int,int>作为testA[1]的值,最终输出包含了这个新增的元素。这其实是QMap的设计特性,而非bug。
核心原因:operator[]的自动插入行为
当你使用QMap::operator[]访问一个不存在的键时,这个运算符会自动执行以下操作:
- 构造一个对应值类型的默认对象(这里就是空的
QMap<int,int>) - 将这个默认对象插入到QMap中,关联到你访问的键(也就是
1) - 返回这个新插入元素的引用
所以当你调用testA[1].begin()时,testA[1]已经被创建出来了,自然能正常获取迭代器,不会报错。
Qt为什么要这么设计?
这种设计是为了简化开发者的代码编写:
- 你可以直接写出
testA[key] = value这样的代码,不用先手动检查键是否存在,再调用insert()方法,减少了冗余的判断逻辑。 - 这种行为和C++标准库中的
std::map::operator[]保持一致,熟悉标准库的开发者能快速上手QMap。 - 在很多场景下,自动创建默认元素是符合直觉的,比如统计计数、构建嵌套容器等场景,能大幅提升开发效率。
如果不想自动创建元素怎么办?
如果你的需求是避免自动插入不存在的键,可以使用QMap::find()方法来检查键的存在性:
#include <QMap> #include <QDebug> int main() { QMap<int, QMap<int, int>> testA; testA [0][0] = 1; auto outerIt = testA.find(1); if (outerIt != testA.end()) { // 键1存在,才进行迭代 QMap<int,int>::iterator innerIt; for(innerIt = outerIt->begin(); innerIt != outerIt->end(); innerIt++){ qDebug()<<"Why am I working!? "; } } qDebug()<<" testA " << testA; // 这里testA不会包含键1的元素 }
这样就能保证只有当键确实存在时,才会去访问对应的元素,不会自动插入新元素。
内容的提问来源于stack exchange,提问作者Aleksandr Krasikov
相关产品推荐
相关产品推荐

