`
美丽的小岛
  • 浏览: 309473 次
  • 性别: Icon_minigender_1
  • 来自: 大连
社区版块
存档分类
最新评论

map注意的两个问题

    博客分类:
  • c
  • c++
 
阅读更多
代码1
void main() 
{

        map< int, int* > mapInt;

        for ( int i = 0; i < 5; i++ )
         {

               mapInt[ i ] = new int( i );
        }

        // 再插入键值为2的元素

        mapInt[ 2 ] = new int( 2 );

        // 做一些操作

        // 删除内存。

        map< int, int* >::iterator itMap = mapInt.begin();

        for ( ; itMap != mapInt.end(); ++itMap ) {

                delete itMap->second;

        }
}

 

 

代码2
void main() {

     map< int, int > mapInt;

     for ( int i = 0; i < 5; i++ ) 
     {

          mapInt.insert( make_pair( i, i ) );

     }

     mapInt.insert( make_pair( 5, 2 ) );

     // 删除所有实值为2的元素

     map< int, int >::iterator itMap = mapInt.begin();

     for ( ; itMap != mapInt.end(); ++itMap )
     {

           if ( itMap->second == 2 )
           {
                  mapInt.erase( itMap );
              }
       }
}

 

代码1   将导致内存泄露,因为mapInt[ 2 ] = new int( 2 );这条语句把原来键值为2的元素的实值指针覆盖了,原来的指针就成为野指针,导致内存泄露。
map容器插入元素的方法。可以调用map容器的insert成员函数插入元素,或者直接用map容器的下标运算式赋值,但这里有一个地方要注意,如果实值为指针的话,插入重复键值的元素时,会导致内存泄露。所以对于插入元素时,必须检查是否插入成功。

正确的方法:
void main() { 
map< int, int* > mapInt;
bool bRet;
for ( int i = 0; i < 5; i++ ) {
int* pI = new int( i );
bRet = mapInt.insert( make_pair( i, pI ) ).second;
if ( !bRet ) {
// 插入元素不成功。
delete pI;
}
}
// 再插入键值为2的元素
int* pI = new int( 2 );
bRet = mapInt.insert( make_pair( 2, pI ) ).second;
if ( !bRet ) {
// 插入元素不成功。
delete pI;
}
// 做一些操作
// 删除内存。
map< int, int* >::iterator itMap = mapInt.begin();
for ( ; itMap != mapInt.end(); ++itMap ) {
delete itMap->second;
}
}

 

代码2 将导致程序未定义的错误,在windows中即是访问非法内存,程序当掉。因为mapInt.erase( itMap );调用后itMap迭代器已无效了,所以当执行++itMap时,访问非法内存,导致程序当掉。

如果erase()总是返回下一元素的位置,那就可以像在vector容器中删除元素一样,如:

// 删除所有实值为2的元素

map< int, int >::iterator itMap = mapInt.begin();

for ( ; itMap != mapInt.end(); ) {

if ( itMap->second == 2 ) {

itMap = mapInt.erase( itMap ); 

}

else {

++itMap;
}
}

但是,注意,以上的方式只在vc使用P.J.STL中才能编译通过,而使用SGI STL库则编译不过,因为SGISTL库在设计中考虑到如果用户不需要这一特性,就会损失性能,因此否决了这种想法。所以要保证可移植性,最好采用下面的方法:

// 删除所有实值为2的元素

map< int, int >::iterator itMap = mapInt.begin();

for ( ; itMap != mapInt.end(); ) {

if ( itMap->second == 2 ) {

// itMap++将使itMap指向下一个元素,但返回原迭代器的副本,所以

// erase()被调用时,itMap不指向将要被删除的元素

mapInt.erase( itMap++ );
 

}

else {

++itMap;

}

}

分享到:
评论

相关推荐

    详解Java8合并两个Map中元素的正确姿势

    在Java8中,合并两个Map中的元素是一项常见的操作,尤其是在处理数据集合时。本文将深入探讨如何正确地合并两个Map,重点介绍两种方法:`Map.merge()` 和 `Stream.concat()`。这两种方法在处理Map合并时有各自的特点...

    详解Go开发Struct转换成map两种方式比较

    本文将介绍两种在Go语言中将Struct转换为map的方法,并对它们进行比较。 首先,我们定义了一个Persion结构体,其中包含了多个字段,这些字段的类型为int、string、bool等基本类型,这样的结构体类型是Go语言中常见...

    c++中map的基本用法和嵌套用法实例分析

    遍历嵌套`map`可以使用两个迭代器: ```cpp map, map, int&gt;&gt;::iterator multitr; map, int&gt;::iterator intertr; for (multitr = multiMap.begin(); multitr != multiMap.end(); multitr++) { for (intertr = ...

    groovy中map的基本操作1

    比较Map是否相等,可以使用`==`运算符,它会检查两个Map的键值对是否完全匹配,如`assert map == other`。`toSet()`函数用于将列表转换为Set,以进行无序比较。 总的来说,Groovy中的Map提供了灵活的数据存储和访问...

    将Map转换成Java实体

    在Java编程中,Map对象和Java实体类是两种常见的数据结构。Map对象通常用于存储键值对,而实体类则代表数据库中的记录或者业务逻辑中的对象。在实际开发中,我们有时需要将Map对象的数据转换为Java实体对象,以便...

    STL中map用法详解 STL中map用法详解 STL中map用法详解

    =`用于比较两个map的键值对是否完全相同或不相同,`、`&gt;`、`、`&gt;=`用于比较它们的键序: ```cpp std::map, Value&gt; map1, map2; if (map1 == map2) { /* ... */ } if (map1 &lt; map2) { /* ... */ } ``` 10. **...

    java xml和map互转

    接下来,我们创建一个名为`XmlMapConverter`的工具类,其中包含两个主要方法:`mapToXml`和`xmlToMap`。 `xmlToMap`方法负责将XML字符串解析成Map: ```java import org.dom4j.Document; import org.dom4j....

    对比Route-Map在 Redistribute以及Policy-Routing中的应用及注意点

    重分发可以使两个不同路由协议下的网络互相交流路由信息,但如果我们需要精确地管理,哪些条目可被重分发。 Route-Map 是一种强大的路由策略工具,需要正确地配置和应用,以免带来不必要的麻烦。

    MapTile切片工具

    - **tpl 和 sys**:这两个文件可能是MapTile的配置模板或系统文件,用于设定切片规则和保存工作环境。 通过阅读使用说明,结合实际的图片和模板,用户可以快速掌握MapTile的使用技巧,从而高效地处理地图切片任务。...

    谷歌地图GoogleMap

    Directions API则用于计算两个或多个位置之间的最佳路线。它可以返回详细的步骤、距离、预计时间和交通情况。这个API在开发导航应用时非常有用。例如,请求从A点到B点的路线: ```http GET ...

    STL中map用法详解

    `map`支持比较操作,如`=`, `, `&gt;`, `, `&gt;=`,这通常用于比较两个map的大小或相等性,但请注意比较的是元素的键而不是值。 6. **multimap** 如果键可以重复,可以使用`multimap`。它和`map`的区别在于键可以有多...

    Map里面containsKey的用法

    这意味着如果两个键`equals()`相等,它们的`hashCode()`也必须相等。这对于哈希表(如`HashMap`)的高效操作至关重要,因为哈希表依赖于`hashCode()`来确定键的位置。 在实际开发中,`containsKey`方法常用于验证键...

    vector与map简介_map_资料_vector_

    - **访问**:使用下标运算符`[]`,如`vec[0]`获取第一个元素,注意下标从0开始。 - **插入和删除**:`push_back()`在末尾添加元素,`insert()`在指定位置插入,`erase()`删除元素。 - **大小和容量**:`size()`返回...

    多线程map容器互斥代码

    这两个线程都需要访问`mapdate`,因此为了防止数据竞争(data race),引入了互斥量`hMutex`作为同步机制。 1. **多线程**:多线程允许程序同时执行多个任务。在这个例子中,创建了一个新的线程`DeliteFunc`,该...

    C++中map容器的说明和使用技巧

    定义map容器可以使用以下两种方式: 1. 直接定义:map, int&gt; my_Map; 2. typedef定义:typedef map, int&gt; MY_MAP; MY_MAP my_Map; 三、插入数据 插入数据可以使用以下四种方式: 1. my_Map["a"] = 1; 2. my_Map....

    Java二维数组实现简单Map

    在这个例子中,map有10个“条目”,每个条目由两个元素组成,第一个元素是键,第二个元素是值。 接下来,我们需要实现Map的基本操作: 1. **插入(Put)**:在二维数组中插入一个键值对意味着找到一个空位(假设...

    Hadoop源代码分析(MapTask)

    MapTask类的成员变量只有这两个,其他的变量都是通过split和splitClass创建的。 MapTask类的run方法是其最重要的方法,负责执行Map任务。run方法首先配置系统的TaskReporter,然后根据情况执行runJobCleanupTask、...

    map总结,原理,使用

    16. **swap()**:交换两个 map 的内容。 17. **upper_bound()**:返回键值大于给定元素的第一个位置。 18. **value_comp()**:返回用于比较值的函数。 #### 六、示例代码 ```cpp // 遍历 map 示例 std::map, ...

    Map2ShpPro

    《Map2ShpPro:GIS数据格式转换工具详解》 Map2ShpPro是一款专用于GIS(Geographic Information System,地理信息系统)数据格式转换...对于那些希望在两种GIS平台间灵活操作的用户,Map2ShpPro是一个值得考虑的工具。

    Java Map 集合类简介

    在Java的`java.util`包中,集合类扮演着重要的角色,其中List和Map是最为常见的两种。List的实现例如ArrayList和Vector,它们都是可变大小的列表,适合存储和操作各种类型对象的序列。特别是ArrayList,基于动态数组...

Global site tag (gtag.js) - Google Analytics