博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
c++野指针 之 实战篇
阅读量:5797 次
发布时间:2019-06-18

本文共 2853 字,大约阅读时间需要 9 分钟。

一:今天做poj上的3750那个题,用到了list的erase方法。提交之后总是报runtime error!

纠结了好长时间。曾有一度怀疑过vector的erase和list的erase处理方式不一样。理论知识请參考也指针和悬浮指针:http://blog.csdn.net/u010700335/article/details/39831293 或 深拷贝和浅拷贝 http://blog.csdn.net/u010700335/article/details/39830425

二:现附上代码。稍后作解释

#include 
#include
#include
#include
using namespace std;const int MAX_SIZE = 20;int main(){ int n,w,s; int i,cp; char str[MAX_SIZE]; list
lists; scanf("%d",&n); for(i=0;i
> str; lists.push_back(str); } scanf("%d,%d",&w,&s); list
::iterator iter; iter = lists.begin(); while(w>1) { iter++; w--; } cp = 1; for(; lists.size()!=0;) { cp++; if(iter == lists.end()) iter = lists.begin(); if(cp<=s) { iter++; } else { cout << *iter << endl; iter = lists.erase(iter);// 由于删除iter,自己主动返回下一个元素的,vector也是一样;否则ter成为野指针。而非自己主动指向下一个,是返回下一个。 cp = 1; } } return 0;}
三:原因例如以下:

程序里面使用了list容器,今天搞清楚了erase()函数的机理。经常使用的删除容器中元素的方法是例如以下(方法1):

      list< int> List;
      list< int>::iterator iter;
      for( iter = List.begin(); iter != List.end(); )
      {
            if(1)  
            {
               iter = List.erase( iter );
            }
            else
            {
               iter++;
            }
      }
      也能够这样写(方法2):
      list< int> List;
      list< int>::iterator iter;
      for( iter = List.begin(); iter != List.end(); )
      {
            if(1)  
            {
               List.erase( iter++ );
            }
            else
            {
               iter++;
            }
      }
     有一种错误的写法(注意同方法2比較)
     list< int> List;
     list< int>::iterator iter;
     for( iter = List.begin(); iter != List.end(); )
     {
            if(1)  
            {
               List.erase( iter );
            }
            iter++;
     }// 
     我们看一下erase()函数的源码(仅列出release下的代码)。

        iterator erase(iterator _Where)
        {    // erase element at _Where
        _Nodeptr _Pnode = (_Where++)._Mynode();
        if (_Pnode != _Myhead)
            {    // not list head, safe to erase
            _Nextnode(_Prevnode(_Pnode)) = _Nextnode(_Pnode);
            _Prevnode(_Nextnode(_Pnode)) = _Prevnode(_Pnode);
            this->_Alnod.destroy(_Pnode);
            this->_Alnod.deallocate(_Pnode, 1);
            --_Mysize;
            }
        return (_Where);
        }
函数在返回的时候,是返回当前迭代器的下一个节点。所以当 iter = List.erase( iter ); 运行以后。迭代器自己主动指向了下一个元素。

而对于入參中的iter。所指的地址已经被销毁,所以写的时候,应该注意加上前面的iter =

四:iter++ 和 ++iter

那另外的一种写法,List.erase( iter++ ); 为什么也是对的呢?这里研究了一下,这里须要讲一下++运算符的操作。

        _Myt_iter& operator++()   // 前面自增
            {    // preincrement
            ++(*(_Mybase_iter *)this);
            return (*this);
            }
        _Myt_iter operator++(int) // 后面自增
            {    // postincrement
            _Myt_iter _Tmp = *this;
            ++*this;
            return (_Tmp);
            }
++实际上能够看做是一个函数。
对于++在后的情况(比如i++),函数在执行的时候,将运算的数据i已经改变。可是函数的返回值是操作之前的数据。所以在我们看来,i++好像是先进行了i的读取。才+1。
回到迭代器,List.erase( iter++ );就没有问题了。
对于那种错误的方法,List.erase( iter );在运行以后,iter所指的对象已经被销毁,所以再对iter进行操作是非法的,程序会出错。

再看一个简单的演示样例:

#include 
using namespace std;class A{public: A(int a=0,int b=0) { x=a; y=b; } A& operator++(); A operator++(int); void out() {cout<
<<","<
<

重载的++ 符号在使用过程中 编译器是不能区分出 ++是前置的还是 后置的?是依据(int)来区分 当给定实參(比方0)时为后置

opertor++();//重载前置++
operator++(int); //重载后置++
c.opertor++;//调用前置
c.opertor++(0);//调用后置
这个是约定俗成

你可能感兴趣的文章
刚毕业从事java开发需要掌握的技术
查看>>
vim
查看>>
Java重写equals方法和hashCode方法
查看>>
Spark API编程动手实战-07-join操作深入实战
查看>>
H3C-路由策略
查看>>
EasyUI基础入门之Easyloader(载入器)
查看>>
java中ArrayList 、LinkList区别
查看>>
Spring ’14 Wave Update: Installing Dynamics CRM on Tablets for Windows 8.1
查看>>
利用rand7()构造rand10()
查看>>
MySQL 备份与恢复
查看>>
吃午饭前,按书上的代码写会儿--Hunt the Wumpus第一个版本
查看>>
easyui中combobox的值改变onchang事件
查看>>
TEST
查看>>
PAT A1037
查看>>
ReactiveSwift源码解析(三) Signal代码的基本实现
查看>>
(六)Oracle学习笔记—— 约束
查看>>
[Oracle]如何在Oracle中设置Event
查看>>
top.location.href和localtion.href有什么不同
查看>>
02-创建hibernate工程
查看>>
information_schema系列五(表,触发器,视图,存储过程和函数)
查看>>