• c++读书笔记(顺序容器)


    1、顺序容器包括:vector,list,deque

    2、接受容器大小做形参的构造函数只适用于顺序容器,而关联容器不支持这种初始化。

    3、作为容器元素类型必须满足以下两个约束:

         一、元素类型必须支持赋值运算。

        二、元素类型的对象必须可以复制。

    上面的两条是最低限度的元素类型约束。除了引用类型外,所有内置或复合类型都可用做元素类型。

    4、只有vector和deque容器提供以下两种重要的运算集合:

      一、迭代器算术运算:iter+n

                                  iter-n

                                  iter1+=iter2

                                 iter1-=iter2

                                 iter1-iter2

     二、除了==和!=之外的关系操作符来比较两个迭代器:>、>=、<、<=

    5、关于添加,插入或删除元素可能会使迭代器失效

    关于这个问题首先要弄清楚vector,list,deque在内存中是怎样存储的:

    vector容器的元素以连续的方式存放——每一个元素都紧挨着前一个元素存储。所以当容器中已经没有空间容纳新的元素,vector必须重新分配存储空间,用来存放原来的元素以及新添加的元素。在vector中某个位置插入一个元素时,该位置后面的元素都要向后移动了。删除某个元素道理与插入一样。

    list容器表示不连续的内存区域,list存储类似于链表,故插入或删除list容器中的一个元素不需要移动任何其他元素。

    下面我给出两端代码来证明vector和list的存储方式:

    #include<iostream>

    #include <vector>

    #include <list>

    using namespace std;

    int main()

    {

    vector<int> vec;

    vec.push_back(3);
    vector<int>::iterator ite=vec.begin();
    cout<<"第一个元素的内容是"<<*ite<<endl;
    cout<<"起始地址是"<<&vec[0]<<endl;

    for(int i=0;i<100000;i++)

    vec.push_back(3);
    cout<<"第一个元素的内容是"<<*ite<<endl;
    cout<<"起始地址是"<<&vec[0]<<endl;

    list<int>li;

    li.push_back(3);

    list<int>::iterator it=li.begin();

    cout<<"第一个元素 的内容是"<<*it<<endl;

    for(int i=0;i<100000;i++)

    li.push_back(3);

    cout<<"第一个元素的内容是"<<*it<<endl;


    getchar();
    }

    运行结果是:

     

    有运行结果可以看出vec起初的起始地址是0x310f18,通过插入10000元素后,起始地址变成了0x320020,说明vector起始的容量已经不能满足再添加10000的要求了,故必须重新开辟一块内存空间来存放元素。同时该程序也说明:vector容器添加元素会使迭代器失效。因为迭代器也是指针,当vector开辟新内存空间来存放更多的元素时候,原来的内存空间就要被收回了,这时候指向以前内存空间的迭代器就成了“野迭代器”了!而list容器迭代器经过增加元素后并没有失效,这也从侧面说明list容器在添加元素(不论添加多少个元素)都不需要移动任何其他元素。

    6、容器之间的比较是基于容器内元素的比较。它的比较方法类似于string类型的比较。

    7、front和back   pk    begin和end

       front将返回容器内第一个元素的引用,返回类型是size_type;back将返回容器最后一个元素的引用,返回类型也是size_type

      begin将返回指向容器内第一元素的迭代器,返回类型是iterator;end将返回容器最后一个元素的下一个位置的迭代器,返回类型是iterator

    8、顺序容器中能够使用下表操作的有vector和deque,但是要注意:容器的下表只能用于获取已存在的元素,不能用来添加元素。这两天老是犯这个错误,可能数组毒害太大了!

    9、赋值pk swap

    赋值操作符首先删除其左操作数容器中的所有元素,然后将右操作数容器的所有元素插入到左边容器中:

    c1=c2等价于c1.erase(c1.begin(),c2.end());c1.insert(c1.begin(),c2.begin(),c2.end());

    c1.swap(c2)作用是交换内容:调用完该函数后,c1中存放的是c2原来的元素,c2中存放的则是c1原来的元素。

    c++primer上有这样一段话:该操作不会删除或插入任何元素,而且保证在常量时间内实现交换。由于容器内没有移动任何元素,因此迭代器不会失效。读完就会想:为什么呢?为什么没有元素移动?为什么迭代器不会失效?我当时猜想应该是:该操作只是把分给两个容器的内存的地址进行交换,来实现内容交换!下面我写了代码验证这一想法

    #include <iostream>
    #include <vector>
    using namespace std;
    int main()
    {
        vector<int> vec1;
        vec1.resize(3,2);
        vector<int> vec2;
        vec2.resize(4,4);
        cout<<"交换前两个容器中存储的内存地址:"<<endl;
        cout<<"vec1中存储的内存块的地址是:"<<&vec1[0]<<endl;
        cout<<"vec2中存储的内存块的地址是:"<<&vec2[0]<<endl;
        vec1.swap(vec2);
         cout<<"交换后两个容器中存储的内存地址:"<<endl;
        cout<<"vec1中存储的内存块的地址是:"<<&vec1[0]<<endl;
        cout<<"vec2中存储的内存块的地址是:"<<&vec2[0]<<endl;
        getchar();
    }

    运行结果是:

    这样明白了吧:swap交换的不是两个容器中的内容而是两个容器中存储的地址!所以这样交换前的迭代器也不会失效了!

  • 相关阅读:
    异步文档树解决方案
    兼容IE低版本的文件上传解决方案
    CentOS-常用命令(版本:7.x)
    搭建Nexus3私服(含使用说明,支持CentOS、Windows)
    CentOS-搭建MinIO集群
    GitLab升级(yum安装版v11.11.8~12.0.12)
    yum安装GitLab-v11.11.8(git私服)
    Docker中容器的备份和恢复(可迁移)
    Nexus3配置yum私服
    局域网连接数据慢的方法汇总
  • 原文地址:https://www.cnblogs.com/yongbufangqi1988/p/1788204.html
Copyright © 2020-2023  润新知