迭代器失效的例子

5 篇文章 0 订阅

vector迭代器的使用切不可真正当指针使,尽管底层会调用其偏特化版本,但是它自身调用是基于一个有用的前提:这个指针本身是有效的,即指向地址合法。

现在有个应用:
请编写一个方法,将字符串中的空格全部替换为“%20”。假定该字符串有足够的空间存放新增的字符,并且知道字符串的真实长度(小于等于1000),同时保证字符串由大小写的英文字母组成。
给定一个string iniString 为原始的串,以及串的长度 int len, 返回替换后的string。
测试样例:
“Mr John Smith”,13
返回:”Mr%20John%20Smith”
”Hello World”,12
返回:”Hello%20%20World”

于是我写了下面的代码:

class Replacement {
public:
    string replaceSpace(string iniString, int length) {
        //    
        /*****************错误发生在下面***********/
        string::iterator front = iniString.end()-1;     

        int c = count(iniString.begin(), iniString.end(), ' ');
        iniString.resize(length+c*2, ' ');
        /***************错误发生在上面*************/

        string::iterator back = --(iniString.end());

        while(iniString.begin() != front) {

            if (*front != ' ') {
                *back = *front;
                --back; --front;
            }
            else {
                *back = '0'; --back;
                *back = '2'; --back;
                *back = '%'; --back;
                --front;
            }
        }
        return iniString; 
    }
};

上面可以对迭代器直接+n,因为这个迭代器类型是RandomAcessIterator,所以合法。注意到注释部分,错误就发生在那一部分:段错误,为什么?迭代器失效了!!!

我们知道string的空间也是动态增长的,这个和vector类似,并不是在原有的空间末尾再续空间,而是开辟一个新的、原空间两倍大的内存区域,把原始数据拷贝过来后释放原来的空间。对这个有了了解,重点再看以下句子:

        string::iterator front = iniString.end()-1;     

        int c = count(iniString.begin(), iniString.end(), ' ');
        iniString.resize(length+c*2, ' ');

它的意思就是先找到原来string的最后一个字符,然后把这个string空间扩大,用来把空格替换为“20%”,很好理解。但是第一句话掉入一个陷阱:这个front在resize()之后,并不是我们想要的那最后一个字符的位置,它可能是任何东西,就是不是想要的,原因已经说过了。

那么如何避免这种错误?这只是一个习惯性的约束,因为在很多场合以上写法是合理的,比如list、map、set之类的容器,那么习惯上要保持一致才不容易犯错误,事实上,只需要将有可能造成容器变化的语句放置在迭代器定义之前就好,就像下面:

         int c = count(iniString.begin(), iniString.end(), ' ');
        iniString.resize(length+c*2, ' ');

        string::iterator front = iniString.begin()+length-1;

保持一种习惯,每每碰到问题就会调节反射一般问自己:迭代器会失效吗?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值