C++中std::map的迭代器类型是什么?typeid输出如何解读?
typeid(itr).name()输出乱码的原因 你看到的长串无意义字符是编译器对C类型做**名称修饰(Name Mangling)**后的结果:C标准没有强制规定std::type_info::name()的返回格式,不同编译器、不同ABI版本输出的格式都不相同,GCC、Clang默认返回的就是这种修饰后的内部名称,本身就不是设计给开发者直接阅读的。
itr的实际类型 你代码中map<string, int>的迭代器itr的实际类型是std::_Rb_tree_iterator<std::pair<const std::string, int>>。
这个类型来自STL的内部实现:几乎所有主流STL版本的std::map都是基于红黑树(Red-Black Tree)结构实现的有序关联容器,它的迭代器直接复用了红黑树的迭代器实现,不存在单独的std::map::iterator独立类型——你平时写的std::map<std::string, int>::iterator本质上是这个红黑树迭代器类型的别名(typedef)。
你拿到的输出St17_Rb_tree_iteratorISt4pairIKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEiEE逐段对应实际类型的规则是:
- 前缀
St代表std::命名空间 - 后面跟数字+标识符的格式,数字代表标识符长度:比如
17_Rb_tree_iterator就是长度为17的标识符_Rb_tree_iterator,4pair就是长度为4的标识符pair - 模板参数包裹在
I...EE结构里 - 基础类型缩写直接用单字符表示:比如
i代表int,c代表char,K代表const - 你看到的
NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE就是我们平时用的std::string——它本质是std::basic_string<char, std::char_traits<char>, std::allocator<char>>的类型别名,__cxx11前缀代表这是C++11 ABI版本的实现。
在GCC/Clang环境下,可以调用内置的abi::__cxa_demangle接口把修饰后的类型名转换为可读格式,示例代码如下:
#include <iostream> #include <string> #include <map> #include <typeinfo> #include <cxxabi.h> #include <cstdlib> int main() { std::map<std::string, int> map1; map1.insert({"A",1}); auto itr = map1.begin(); int status = 0; char* readable_name = abi::__cxa_demangle(typeid(itr).name(), nullptr, nullptr, &status); if (status == 0) { std::cout << "itr的可读类型名为:" << readable_name << std::endl; std::free(readable_name); // 该接口返回的内存需要手动释放 } return 0; }
运行后输出为:
itr的可读类型名为:std::_Rb_tree_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> >
注意:
_Rb_tree_iterator是STL内部实现类型,写业务代码时不要直接使用这个类型声明变量,继续用auto或者std::map<Key, T>::iterator即可,不同编译器(比如MSVC)的STL内部map迭代器实现完全不同,直接依赖内部类型会导致代码丧失跨编译器兼容性。
内容的提问来源于stack exchange,提问作者emirhan demir

