QT中指针型QHash<int, SomeClass*>迭代报错及值修改实现咨询
错误根因定位
- 第一类C3867/C2446报错的核心问题:
index_hash是指向QHash实例的裸指针,不是QHash对象本身。你之前直接写index_hash.begin(),根本没触发begin()函数的调用——编译器看到裸指针用点号访问成员,会默认把这个成员函数的地址当表达式返回,拿到的是一个指向成员函数的指针,不是迭代器实例,自然没法和end()返回的迭代器做==比较,才会抛出类型不匹配的错误。 - QHashIterator构造报错的核心问题:
QHashIterator构造函数要的是QHash对象的const引用,你直接传个裸指针进去,类型完全对不上,没法隐式转换;就算后来解引用成*index_hash传参,QHashIterator本身就是为只读遍历设计的,它的value()只给const访问权限,根本不允许修改存储值,所以你之前写的it.value() = item完全不生效。
正确实现方式
方案1:和你最初写的STL风格逻辑兼容,仅修正访问错误
只需要把原来的点号访问换成指针专用的箭头运算符,等价于先解引用指针再调用成员函数,就能拿到正常的可读写迭代器:
QHash<int, SomeClass*>::iterator i; // 用箭头操作符解引用指针,调用真实的成员函数拿到迭代器 for (i = index_hash->begin(); i != index_hash->end(); ++i) { int key = i.key(); // 该迭代器的value()是可读写的,赋值会直接修改哈希存储的指针值 i.value() = item; }
方案2:适配你之前用QHashIterator的Java风格使用习惯
把只读的QHashIterator换成Qt提供的可变版本QMutableHashIterator,传入解引用后的QHash对象引用,就能获得修改权限:
// 注意换用Mutable版本的迭代器,构造时传入解引用后的对象引用 QMutableHashIterator<int, SomeClass*> it(*index_hash); while (it.hasNext()) { it.next(); int x = it.key(); // 该迭代器的value()接口支持读写,赋值会真实作用到哈希存储上 it.value() = item; }
常见注意事项
- 遍历过程中别直接调用
insert()/remove()这类会改动哈希结构的方法,不然会直接导致迭代器失效;如果要删当前位置的元素,直接用迭代器自带的remove()方法就行,或者用QMutableHashIterator提供的setValue()、remove()接口。 - 要分清楚修改目标:如果你是要改哈希里存的
SomeClass*指针本身(也就是换个指向的实例),上面两种写法都能生效;如果你是要改指针指向的SomeClass对象内部的成员,不管用只读还是可写迭代器,直接通过i.value()->对象成员就能改,不受迭代器权限限制。 - 别把裸指针和栈上对象的访问规则搞混:只要是通过裸指针访问类的成员,要么用
->,要么先解引用再用.,不然一定会出现“取成员函数地址”的类型错误。
内容的提问来源于stack exchange,提问作者streamc
相关产品推荐
相关产品推荐

