std::map C++

C++ Builder 2010-06-04 11:37:53 阅读226 评论0   字号: 订阅

std::map 再学习

1.         map中的元素其实就是一个pair

2.         map的键一般不能是指针,比如int*char*之类的,会出错。常用的就用string了,int也行。

3.         map是个无序的容器,而vector之类是有序的。所谓有序无序是指放入的元素并不是按一定顺序放进去的,而是乱序,随机存放的(被映射后近似随机存放)。所以遍历的时候有些效率差别。

4.         判断有没有找到该键的内容可以这样:

//-----------------------------------------------------------------------------------------------

std::map<std::string, Record>::const_iterator cIter;

cIter = stdfile.m_map.find(s);

if (cIter == stdfile.m_map.end())  //没找到就是指向END

{

m_vecMoreFile.push_back(s);

}

//-----------------------------------------------------------------------------------------------

如果键的内容是指针的话, 应该用NULL指针也可以判断了.

5.         遍历:

//-----------------------------------------------------------------------------------------------

std::map<std::string,Record>::iterator iter;

for (iter = m_map.begin(); iter != m_map.end(); iter++)

{

std::string s = iter->second.filename;

}

//-----------------------------------------------------------------------------------------------

由于map内容可以相当一个PAIR,那就简单了,用iter->second就可以取得值了。

 

std::map的一些注意点

std::map是一个很常用的标准容器,采用红黑树或者平衡二叉树来储存节点内容,具有对数复杂度的插入时间和查找时间。这里简单说下它的一些值得注意的关注点。

1.         插入:

//-----------------------------------------------------------------------------------------------

std::map<int, std::string> str_map;

str_map.insert ( std::pair<const int, std::string>(2, "bb") );      //没有转型操作

str_map.insert ( std::pair<int, std::string>(2, "bb") );     //需要转型成std::pair<const int, std::string>再进行插入

str_map.insert ( std::make_pair(3, "cc") );          //同上,需要转型

str_map.insert ( std::map<int, std::string>::value_type ( 4 , "dd" ) );      //没有转型操作

//-----------------------------------------------------------------------------------------------

还有一种方法是通过索引器[]去直接插入,这种方法在下边再讨论。

2.         删除:

一种很常见的错误是:

//-----------------------------------------------------------------------------------------------

for ( map<int, string>::iterator it = str_map.begin(); it!=str_map.end(); it++ )

{

       if ( some_condition ) str_map.erase(it);

}

//-----------------------------------------------------------------------------------------------

删除操作会使it乱掉,再使用it++就出错了。

正确的做法是:

//-----------------------------------------------------------------------------------------------

for ( map<int, string>::iterator it = str_map.begin(); it!=str_map.end(); )

{

       if ( some_condition ) {

              str_map.erase(it++);

       } else {

              it++;

       }

}

//-----------------------------------------------------------------------------------------------

3.         索引:

str_map[5] = "ee";

这条语句实际上是分两个步骤执行的:先在str_map[5]的地方构造一个空string,然后通过str_map[5]返回这个stringreference;然后调用这个空stringassignment运算符,把"ee"赋给它。因此,这样写要比直接insert效率低些。

索引还有一个问题是需要注意的:

//-----------------------------------------------------------------------------------------------

map<int, string> m;

cout<<m.size()<<endl; // output: 0

if ( m[4] == "aa" ) some_operation();

cout<<m.size()<<endl; //output: 1

//-----------------------------------------------------------------------------------------------

这里m[4]已经指向了一个构造好了的空string

4.         function object

std::mem_fun的帮助下,vector等容器可以很容易地使用find_if等泛型算法,比如:

class X {

public:

       bool condition();

};

vector<X> vx;

....

vector<X>::iterator it = std::find_if ( vx.begin(), vx.end(), std::mem_fun(&X::condition) );

由于map::iterator指向的是std::pair,所以要使用这些算法大部分时候就只好自己手写相应的function object了。

但借助boost lambda库的帮助,我们就可以省去自己写function object的麻烦了:

#include <boost/lambda/bind.hpp>

#include <boost/lambda/lambda.hpp>

using boost::lambda::bind; 

std::map<int, X> mx;

....

std::map<int, X>::iterator it = find_if ( mx.begin(), mx.end(),

       bind ( &X::condition, bind(&std::map<int, X>::value_type::second, _1) ) );

 

 

 

 

转自:http://blog.163.com/andy-su/blog/static/28174174201054113753538/

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐