C++中的insert()与迭代器

        这段时间断断续续地重读C++ Primer,发现了一个比较有趣的点,309页的练习9.22这道题:

        此题共有两个错误,一个是while陷入了死循环,因为insert()函数返回的是插入点之前的迭代器,因此while循环的条件永远为真,这是比较明显的;另一个错误是mid这个迭代器会失效,这是比较值得研究的点,对此github上Cpp-Primer项目的几个contributor也展开了讨论,现将其总结为本文。

        如同书里315页的9.3.6所说

 

        此处插入的点在vector的mid迭代器之前,那么必然会导致插入位置之后,也就是mid这个迭代器失效,怎么来判断迭代器失效了呢?看看下面的代码(运行环境:Clion):

void Func9_22()
{
    vector<int> v1 = {0, 1, 2, 3, 4, 5};
    auto m = [&] {return v1.begin() + v1.size() / 2};
    vector<int>::iterator vb = v1.begin();
    vector<int>::iterator vm = v1.begin() + v1.size() / 2;
    v1.insert(vb, -1);
    cout << "vb = " << *vb << endl;
    cout << "vm = " << *vm << endl;
    cout << "vb's position:" << vb - v1.begin() << endl;
    cout << "vm's position:" << vm - v1.begin() << endl;
    cout << "v1 = " << *v1.begin() << endl;
}

        此时输出如下:

vb = 0

vm = 3

vb's position:-8

vm's position:-5

v1 = -1

        显然,vector的begin()还是mid的位置都已经改变了(但是他们对应的值还是不变的)。

        接下来再看看下面的代码:

#include <iostream>
#include <vector>

void double_and_insert(std::vector<int>& v, int some_val)
{
    auto mid = [&]{ return v.begin() + v.size() / 2; };
    for (auto curr = v.begin(); curr != mid(); ++curr)
        if (*curr == some_val)
            ++(curr = v.insert(curr, 2 * some_val));
}

int main()
{
    std::vector<int> v{ 1, 9, 1, 9, 9, 9, 1, 1 };
    double_and_insert(v, 1);

    for (auto i : v) 
        std::cout << i << std::endl;
}

        这里最显著的差别就是mid的定义:

auto mid = [&]{ return v1.begin() + v1.size() / 2; };

        这是C++的lambda表达式,相当于定义了一个mid的无参数函数,返回的是v1.begin() + v1.size() / 2,需要注意的是,这是一个动态的过程,即这个索引会在程序运行过程中动态改变,当插入了新的元素后,v1的size()发生了变化,此时mid也会随之改变。

        一开始就定义mid这里,是一个静态的过程,即定义好mid后,就永久指向了定义时的索引,哪怕后面插入了新的元素,也不会发生改变。

vector<int>::iterator mid = v1.begin() + v1.size() / 2;

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值