• C++ Primer : 第九章 : 顺序容器的操作以及迭代器失效问题


    顺序容器的添加、访问、删除操作以及forward_list的特殊操作,还有迭代器失效问题。


    一、向容器添加元素

    // array不支持这些操作
    // forward_list有自己撰于的版本的insert和emplace
    // forward_list不支持push_back和emplace_back
    // vector和string不支持push_front和emplace_front
    c.push_back(t);         在c的尾部创建一个值为t或由arg创建的元素
    c.emplace_back(arg);    函数返回void
    c.push_front(t);        在c的头部创建一个值为t或由arg创建的元素</span>
    c.emplace_front(arg);   函数返回void
    c.insert(p, t);         在迭代器p指向的元素之前创建一个值为t或有arg创建的元素
    c.emplace(p, t);        函数返回指向新添加元素的迭代器
    c.insert(p, n, t);      在迭代器p指向元素之前插入n个值为t的元素,函数返回指向新添加的第一个元素的迭代器,若n为0,则返回p
    c.insert(p, b, e);      在迭代器p指向元素之前插入迭代器b到e(不包括e)之间的元素,b和e不能指向c中元素,返回新添加的第一个元素的迭代器,若范围为空,则返回p
    c.insert(p, il);        在迭代器p指向元素之前插入由花括号包围的初始值列表 il 的元素,函数返回指向新添加的第一个元素的迭代器,若列表为空,则返回p



    当容器调用push或insert成员时,这些对象被拷贝到容器中,而进行emplace操作时,则是将参数传递给容器的构造函数,emplace使用这些参数在容器里直接构造一个元素。

    因此,emplace的参数必须与元素类型的构造函数的参数相匹配。


    二、访问元素


    除了array、每个顺序容器都有一个front成员函数,除了forward_list之外的所有顺序容器都有一个back成员函数,这两个操作分别返回首元素和尾元素的引用


    // at和下标操作值适用于string、vector、deque和array
    // back不适用于forward_list
    c.back();      返回c的尾元素的引用,若c为空,则行为未定义
    c.front();     返回c的首元素的引用,若c为空,则行为未定义
    c[n];          返回c中下标为n的元素的引用,n是一个无符号整数
    c.at(n);       返回下标为n的引用。如果下标越界,则抛出一个 out_of_range异常 



    三、删除元素

    // 这些操作不适用于array
    // forward_list有特殊版本的erase,并且它不支持pop_back; 
    // vector和string不支持pop_front
    c.pop_back();      返回c中的尾元素/首元素,若c为空,则函数行为未定义
    c.pop_front();     函数返回void
    c.clear();         删除c中所有元素,返回void 
    c.erase(p);        删除c中p指向的元素,返回指向被删元素之后元素的迭代器,如果p指向尾元素,则返回尾后迭代器,若p为尾后迭代器,则行为未定义 
    c.erase(b, e);     删除迭代器b和e(不包括e)之间的元素,返回指向被删元素之后元素的迭代器, 若e为尾后迭代器,则返回e 
    



    四、特殊的forward_list操作

    由于在单项链表中,没有简单的方法来获取一个元素的前驱,所以在forward_list中定义了首前迭代器。


    lst.before_begin();          返回指向链表首元素之前不存在的元素的迭代器,c开头的是const_iterator版本 
    lst.cbefore_begin();         不能解引用此迭代器
    
    lst.inert_after(p, t);       在迭代器p之后插入元素,t是一个对象 
    lst.inert_after(p, n, t);    n是数量
    lst.inert_after(p, b, e);    b、e表示范围的一对迭代器(不能指向lst) 
    lst.inert_after(p, il);      il是一个花括号的初始化列表,返回一个指向插入的最后一个元素的迭代器,如果范围为空,返回p,如果p为尾后迭代器,则行为未定义
    lst.emplace_after(p, arg);  在p指向的位置之后插入由arg构造的元素,返回指向这个新元素的迭代器,如果p是尾后迭代器,则行为未定义
    lst.erase_after(p);          删除p之后的元素,或删除b到e(不包括e)之间的元素,返回一个指向被删元素之后元素的迭代器
    lst.erase_after(b, e);       如果不存在这样的元素,返回尾后迭代器,若p指向lst的尾元素,或p是lst的尾后迭代器,则行为未定义。



    在forwar_list中添加或删除元素时,我们要关注的是:指向要处理的元素的迭代器和其前驱迭代器。

    例:从forward_list中删除奇数

    forward_list<int> flst = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    auto prev = flst.before_begin(); // 获取首前迭代器
    auto curr = flst.begin();
    while (curr != flst.end()){
        if(*curr % 2)
            curr = flst.erase_after(prev); // 删除当前元素,将curr定位到新的第一个元素
        else
            prev = curr ++; // 移动首前元素和当前元素
    }



    五、改变容器大小


    // resize不适用于array
    c.resize(n);     调整c的大小为n个元素,若n < c.size(); 则多出的元素被丢弃,否则对新添加的元素进行值初始化
    c.resize(n, t);  调整c的大小为n个元素,任何新添加的元素都被初始化为t
    // 如果resize缩小了容器,则指向被删除的元素的迭代器、引用和指针都会失效,对vector、string和deque进行resize可能导致迭代器、引用和指针失效




    六、容器操作和迭代器失效问题

    向容器中添加元素后:


    1. 如果容器时vector或string,且存储空间被重新分配,则指向容器的迭代器、指针和引用都会失效,如果存储空间未重新分配,则指向插入元素之前的迭代器、指针和引用都有效,指向插入元素之后元素的迭代器、指针和引用都会失效。

    2. 对于deque,插入到除首尾位置之外的任何位置都会导致迭代器、引用和指针失效,如果在首尾位置添加元素,迭代器会失效,但指向存在的元素的引用和指针不会失效。

    3. 对于list和forward_list,指向容器的迭代器(包括尾后迭代器和首前迭代器)、指针和引用都有效


    容器在删除元素后:

    1.  对于list和forward_list,指向容器的迭代器(包括尾后迭代器和首前迭代器)、指针和引用都有效

    2. 对于deque,如果在首尾之外的任何位置删除元素,那么指向删除元素外其他元素的迭代器、引用和指针也会失效。如果是删除deque的尾元素,则尾后迭代器失效,但其他迭代器、引用和指针不受影响; 如果删除首元素,这些也不会受影响。

    3. 对于vector和string,指向被删除元素之前元素的迭代器、引用和指针扔有效


    当我们删除元素时,尾后迭代器总是会失效!


    因此,必须保证每次改变容器的操作之后都正确的重新定位迭代器,还有,不要保存end返回的尾后迭代器。


  • 相关阅读:
    Redis中两种持久化机制RDB和AOF
    Redis缓存穿透,缓存击穿,缓存雪崩原因+解决方案
    正则匹配日期
    Linux笔记oom时anon rss和total vm的含义
    go笔记time ticker泄露的排查
    C++笔记编译优化:RVO、NRVO
    C++笔记成员变量的初始值
    Redis Java客户端Jedis入门
    vs2005下安装windows sdk v7.1 出现:uuid.lib(unknwn_i.obj) : fatal error LNK1103 或uuid.lib(oaidl_i.obj) : fatal error LNK1103
    查看Nginx的状态
  • 原文地址:https://www.cnblogs.com/averson/p/5096075.html
Copyright © 2020-2023  润新知