STL : List使用时应注意的问题

这篇文章所述只是本人遇到的问题,仅供参考。

#include<list>
#include<iostream>

using namespace std;

class Foo
{
public:
    Foo(int i) {m_iData = i;}
    void setData(int i ) {m_iData = i;}
    int GetData() {return m_iData;}
private:
    int m_iData;
};
// 为了提高可读性,定义容器和迭代器的名字
typedef list<Foo*> FooList;
typedef FooList::iterator FooListItor;

void main()
{
    FooList c; // 创建一个链表容器

//将三个不同的元素填入链表中
    c.push_back(new Foo(1));
    c.push_back(new Foo(2));
    c.push_back(new Foo(3));
//迭代遍历链表
    for(FooListItor itor = c.begin();itor != c.end();)
    {
        if((*itor)->GetData() == 2)
        {
            delete (*itor);
            itor = c.erase(itor);
        }
        else
            ++itor;
    }

//确保所有的对象被删除,链表不会自动完成该项任务
for(FooListItor itor2 = c.begin(); itor2 != end();++itor2)
    delete (*itor2);
}    

使用指针指向动态分配内存的结构或对象时,有几件事情需要注意。

1. 你要负责在使用完对象后释放所有分配的内存。容器并不知道将使用何种类型,所以它们不可能帮你自动释放内存。

2. 许多运算可能会失败,这是因为它们直接对对象或结构的指针进行操作,而不是对对象或结构本身。比如链表的sort()函数,它使用<运算符来比较值并以此结果进行排序。就算运算符对类Foo是合法的,但链表的排序仍是按照指针的实际值而不是对象中数据的值。因而有必要设计自己的比较运算符,在比较之前先对指针解引用。

3.记住,复制容器时,复制的仅仅是指针而不是对象。如果产生了重复的指针,将极难确定哪一个对象需要删除。解决办法是使用智能指针(smart pointer),或避开容器间复制元素的STL的例程或算法。

4.注意,在迭代遍历链表的时候,从链表中删除元素要非常小心。因为删除当前指向的元素将导致迭代器失效,所以你必须确保正确使用erase()函数的返回值,它是这个函数将检索出的容器中的下一个合法位置,通过将这个返回值分配给老的迭代器,我们就跳过了非法位置。但是这又给我们带来了新的问题。当for循环在循环结束处试图对迭代器递增,由于我们已经用erase()将迭代器递增到了下一个位置,因此就会出现问题。为了解决这个问题,我们将递增运算从for循环体移到了循环中的条件选择语句内,在元素没有删除时才进行递增。(一般来说,最好使用算法从容器中删除元素,而不是手工迭代来做,如算法remove_if()就能安全有效地进行该项操作)。

时间: 2024-08-05 03:39:31

STL : List使用时应注意的问题的相关文章

STL map使用时应注意的一个问题

map进行插入时,可使用数组或insert的方法,如下代码: map<int, int> m; m[2] = 12; m[5] = 15; m[3] = 13; <span style="font-family: Arial, Helvetica, sans-serif;">m.insert(map<int, int>::value_type(2, 12));</span> m.insert(map<int, int>::va

Promise使用时应注意的问题

最近在使用axios库时遇到了个问题,后端接口报了500错误,但前端并未捕获到.1. 调用接口的业务代码如下: 1 // 业务代码调用 2 axios({ 3 url: url, 4 method: 'post', 5 data: data 6 }).then(res => { 7 // 提示用户数据更新成功 8 // 问题:后端接口明明报了500错误,但代码确运行到了这里,导致前端界面提示更新成功 9 }).catch(err => { 10 // 提示用户更新失败 11 // 问题:本该运

【纯干货】SVN使用时应注意的那些事

一.SVN使用步骤 检出 checkout 更新 update 冲突 confilicte 添加 Add (没有添加项目可不写) 填写svn日志 提交 commit你以为到这儿就结束了吗?....NO!!! go on ..对svn的操作,一般不建议直接右键项目-team-提交/更新:建议统一在资源库中进行更新.添加.提交等一系列事务.因为在资源库中,对各项待改变或已改变的文件有很直观的比较 二.注意事项: 提交的时候必须写日志(svn试用与团队开发,一个团队中可能有多个人对一个文件进行操作,如

protobuf在使用时出现的问题小汇总

文章开头放一下IBM的google protocol buffer的介绍链接.http://www.ibm.com/developerworks/cn/linux/l-cn-gpb/ 对于这种技术不断更新的东西,我只能这么理解:因为技术在更新,版本在变化,之前很详尽的技术博文可能在之后的版本中遇到无法预知的问题,所以我们在使用时要注意甄别.废话不多说,进入正文部分. 安装什么的都是小问题了,还是贴一下步骤吧. tar -xzf protobuf-2.5.0.tar.gz cd protobuf-

Toolbar 和 CollapsingToolbarLayout一起使用时menu item无点击反应解决办法

昨天一直在琢磨为什么Toolbar和CollapsingToolbarLayout一起使用时menu item无点击放应的原因,后来在stackoverflow上一条回答,说可能是Toolbar的背景颜色太深导致点击时的水波纹不明显.这个启发了我,会不会是跟toolbar的背景有关呢?贴上代码: <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res

EntityFrameWork 使用时碰到的小问题

EntityFrameWork 使用时碰到的小问题 1,在使用orm访问数据库的相目里,也要引用EntityFrameWork.dll,否则无法使用orm 否则,编译错误 错误 5 "System.Data.Entity.DbSet`1<DbAccess.Entity.Dept>"不包含"Where"的定义,并且找不到可接受类型为"System.Data.Entity.DbSet`1<DbAccess.Entity.Dept>&qu

Highcharts使用时遇到的问题及解决方案

Highcharts使用时遇到的问题及解决方案 Highcharts图表控件功能强大,对细节处理得很细致,是目前使用最为广泛的图表控件.本文总结了作者在使用Highcharts时遇到的问题及解决方案. 1. 图表颜色设置 图表的边框色,背景色及点.线的颜色都是可以设置的,其中边框色(borderColor).背景色(backgroundColor)在chart中设置: chart: { backgroundColor: 'pink',// 背景色 borderColor: 'red',// 边框

bootstrap使用时 细节心得

最近国庆7天 还原某丽说 APP PC端网页(作业)时  全程使用bootstrap制作 也遇到了以前很少碰到过的问题 bootstrap 本身修改了某些默认样式  即使在 未给标签class命名某个bootstrap模板时  某些标签也被修改过  这样会容易使某些像我一样的新手误以为自己写的代码哪里出了问题  而浪费很多时间去找一个 没有错误的错误  所以在这里给各位同学做个温馨提示 例如 fieldset 中 lengd标签中的文字 应该是水平居中 位于两侧横线中间 并且垂直居中于横线 但在

c语言:宏里面参数不加括号容易出错,在使用时尽量加括号及举例

宏里面参数不加括号容易出错,在使用时尽量加括号 程序1: #include<stdio.h> #define SQARE(X) X*X int main() { int  n = 10; int m=SQARE(n); printf("m=%d\n",m); return 0; } 结果: m=100 请按任意键继续. . . 分析:貌似没有出问题,请看下面两个例子 程序2: #include<stdio.h> #define SQARE(X) X*X int