赞
踩
关于迭代器( iterator ) ,我们知道,所有 标准库容器 都可以使用迭代器(string 不是标准库容器,也支持迭代器)。
类似于指针类型,迭代器提供了对 对象的间接访问。
今天(2018-4-18),我想测试一下 map 的两个特性:
看程序:
- // mvector.cpp
- #include <iostream>
- #include <map>
- #include <vector>
- #include <algorithm>
- #include <string>
- using namespace std;
-
- int main(){
- map<vector<int> ,string> m;
- vector<int> vi1;
- vi1.push_back(2);
- vi1.push_back(1);
- m.insert(make_pair(vi1,"cx"));
-
- vector<int> vi2;
- vi2.push_back(1);
- vi2.push_back(2);
- m.insert(make_pair(vi2,"mitre"));
- cout<<"m.size : "<<m.size()<<endl;
-
- vector<int> vi3;
- vi3.push_back(3);
- vi3.push_back(4);
- sort(vi3.begin(),vi3.end());
- m.insert(make_pair(vi3,"hello"));
- cout<<"m.size : "<<m.size()<<endl;
-
- vector<int> vi4;
- vi4.push_back(4);
- vi4.push_back(3);
- sort(vi4.begin(),vi4.end());
- m.insert(make_pair(vi4,"world"));
- cout<<"m.size : "<<m.size()<<endl;
-
- map<vector<int>,string>::iterator mi=m.begin();
- while(mi != m.end()){
- //1
- //vector<int>::iterator vi=mi->first.begin();
- //while(vi != mi->first.end()){
-
- //2
- vector<int>::const_iterator vi=mi->first.begin();
- while(vi != mi->first.end()){
-
- //3
- //vector<int> v=mi->first;
- //vector<int>::iterator vi=v.begin();
- //while(vi != v.end()){
-
- //4
- //auto vi=mi->first.cbegin();
- //while(vi !=mi->first.cend()){
- cout<<*vi<<' ';
- ++vi;
- }
- cout<<" "<<mi->second<<endl;
- ++mi;
- }
- return 0;
- }
输出结果:
分析:
可以看出,vector<int> 作为map 的关键字,如果两个vector相等(排序后的 vi3==vi4 ),那么map.insert只会插入一个vecotr对象。
注意到程序中的注释1, 2, 3, 4 ,注释1 在编译时有以下错误( 其他三个都能得到正常输出 ):
-----
mvector.cpp:40:43: error: conversion from ‘std::vector<int>::const_iterator {aka __gnu_cxx::__normal_iterator<const int*, std::vector<int> >}’ to non-scalar type ‘std::vector<int>::iterator {aka __gnu_cxx::__normal_iterator<int*, std::vector<int> >}’ requested
vector<int>::iterator vi=mi->first.begin();
-----
原来是我把 const_iterator 赋值给了 iterator 导致了这个错误!!!!
map 中 元素的类型(value_type) 是 pair<const key_type, mapped_type> ,关键字类型是const 修饰的!!!
在我的程序中,map 的关键字是 const vector<int> ,那么这个vector 的迭代器是const_iterator 。在注释1 中,直接把const_iterator 赋值给了 iterator ,编译出错了!!!
这里的const_iterator 相当于 底层const(low-level const)指针,不能把一个底层const的 指针赋值给一个普通指针。(这很好理解,如果能赋值的话,这个普通指针就可以改变 const对象 的内容了!!)
----------------------------------------------------
补充说明: const 限定符[1]
如果我们想定义一个变量,变量的值不能被改变,就可以用const ,用const修饰的也变量称为常量。
如:
const int coni = 100; // 这个 coni 的值不能被改变!!
int j = coni ; // 可以把 整型常量coni 赋值给 变量j 。作为右值,只是取其值,又不会改变,当然可以!
当 指针/引用 和 const 在一起的时候,就出现了 所谓的顶层const 和 底层const
比如说指针:
注:
底层const(low-level const):指向常量的指针和对常量的引用(引用的const都是底层的)。
不是底层const ,就是顶层const。
顶层const(top-level const):定义的对象是常量(对于指针对象,指针本身是常量;对于其他对象,对象本身是常量)
举个栗子:
- const int ci = 0 ; //ci 值不能改变, 定义的ci对象本身就是常量, 顶层
- int *const p1 = &ci ; //p1 的值不能变,定义的p1指针本身就是常量(常量指针),顶层
-
- //底层const 的必要条件,定义的是指针/引用
-
- int i = 0;
- const int *p2 = &ci ; // p2 是指向常量的指针,底层 。注:指向常量的指针 可以 指向非常量
- const int &r = ci ; // r是对常量的引用,底层。 注:对常量的引用 可以 引用非常量
-
- const int *const p3=p2; //靠左为底层const, 靠右为顶层const
-
-
作为右值 (在赋值= 的右侧) :
----------------------------------------------------
注释1 的错误很明显了!
注释2 纠正了注释1 的错误,正确。
注释3 和注释1 对比:验证了 补充说明 里的最后两句话。
关键字类型是const vector<int> , 我们可以把这个顶层const 赋值 给一个变量;再对变量操作,就没有底层const_iterator 的限制了。
注释4用到了C++11 特性(auto,cbegin,cend)。
References:
[1] C++ Primer , 5E (中文版)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。