zoukankan      html  css  js  c++  java
  • C++学习之路: STL探索 vector 和 list

    引言: 这篇文章写在我们窥探庞大的STL 库之前,先熟悉一下基本操作,用于练手, 也用于过段时间的复习。

    1.可以用一个容器去初始化另外一个容器。

    但是两个容器的类型和内置类型都必须一致,否则编译无法通过。

     1 #include <iostream>
     2 #include <string>
     3 #include <vector>
     4 using namespace std;
     5 
     6 //用一个容器去初始化另一个容器
     7 int main(int argc, const char *argv[])
     8 {
     9     vector<int> vec;
    10     vec.push_back(12);
    11     vec.push_back(89);
    12     vec.push_back(34);
    13     vec.push_back(23);
    14     vec.push_back(56);
    15 
    16     vector<int> vec2(vec);
    17     for(int t : vec2)
    18     {
    19         cout << t << " ";
    20     }
    21     cout << endl;
    22 
    23     return 0;
    24 }

    2.也可以用一段迭代器范围,去初始化另外一个容器:

    同样迭代器也必须是该类型 的迭代器,这是基本要求,不要去尝试一些莫名其妙的初始化,例如用vector<string> 去初始化 vector<int> ,这种低级的错误

     1 #include <iostream>
     2 #include <string>
     3 #include <vector>
     4 #include <algorithm>
     5 using namespace std;
     6 
     7 //用一段迭代器范围去初始化另一个容器
     8 int main(int argc, const char *argv[])
     9 {
    10     vector<int> vec;
    11     vec.push_back(12);
    12     vec.push_back(89);
    13     vec.push_back(34);
    14     vec.push_back(23);
    15     vec.push_back(56);
    16 
    17     vector<int>::iterator it1, it2;
    18     it1 = vec.begin(); //12
    19     it2 = find(vec.begin(), vec.end(), 23);   
    20 
    21     vector<int> vec2(it1, it2);  //作为vec2的参数的两个迭代器it1和it2 也必须是vector<int>::iterator 类型,用vector<xxxxx> ::iterator 作为参数是不会通过编译的
    22     for(int i : vec2)
    23     {
    24         cout << i << " ";
    25     }
    26     cout << endl;
    27     return 0;
    28 }

    综上:我们在用容器,迭代器等方法去初始化另外一个容器,类型匹配是最基本的要求。

     3.下面看一个错误的例子:

     1 #include <iostream>
     2 #include <string>
     3 #include <vector>
     4 #include <algorithm>
     5 using namespace std;
     6 
     7 //用一段迭代器范围去初始化另一个容器
     8 int main(int argc, const char *argv[])
     9 {
    10     vector<int> vec;
    11     vec.push_back(12);
    12     vec.push_back(89);
    13     vec.push_back(34);
    14     vec.push_back(23);
    15     vec.push_back(56);
    16 
    17     vector<double> vec2(vec); //vector<int> 与vector<double>类型不同
    18 
    19 
    20     return 0;
    21 }

    上述代码,编译出现错误,因为vec2是一个vector<double> 类型,而vec是一个vector<int> 类型,两个容器类型不匹配。

    4.容器类型不一样,无法使用一个容器初始化另外的方法,

    却可以使用迭代器范围的方法,用一个容器的迭代器范围去初始化另外一个。   前提是它们的内置类型必须相近,如 int 和 double 

     1 #include <iostream>
     2 #include <string>
     3 #include <vector>
     4 #include <algorithm>
     5 using namespace std;
     6 
     7 //用一段迭代器范围去初始化另一个容器
     8 int main(int argc, const char *argv[])
     9 {
    10     vector<int> vec;
    11     vec.push_back(12);
    12     vec.push_back(89);
    13     vec.push_back(34);
    14     vec.push_back(23);
    15     vec.push_back(56);
    16 
    17     vector<double> vec2(vec.begin(), vec.end());
    18     for(double d : vec2)
    19     {
    20         cout << d << " ";
    21     }
    22     cout << endl;
    23 
    24     return 0;
    25 }

    上面代码所描述的情况就好比, 如果两个碗里面装的东西不一样的时候,它们是不能相互赋值(或初始化)的, 但是当它们*里面的东西*, 差不多的时候,可以用迭代器赋值。

    如果差别太大,则编译不通过 如 迭代器指向的是string类型, 我们却用来初始化 一个vector<int> 容器,显然是不可取的。

    5.当容器不一样,但是内置类型差不多的时候,也可以用迭代器的方法来初始化, 例如我们用vector<int>的 迭代器 来初始化list<int/double> 则是可以的

    因为迭代器指向的内容和vector里面存放的东西差不多,就好像碗和碟子的关系,虽然容器不同,但是里面都是放的同一种食物(好比米饭), 我们就可以把碟子中的米饭,

    复制到碟子里。

     1 #include <iostream>
     2 #include <string>
     3 #include <vector>
     4 #include <list>
     5 #include <algorithm>
     6 using namespace std;
     7 
     8 //用一段迭代器范围去初始化另一个容器
     9 int main(int argc, const char *argv[])
    10 {
    11     vector<int> vec;
    12     vec.push_back(12);
    13     vec.push_back(89);
    14     vec.push_back(34);
    15     vec.push_back(23);
    16     vec.push_back(56);
    17 
    18     list<double> lst(vec.begin(), vec.end());
    19     for(double d : lst)
    20     {
    21         cout << d << " ";
    22     }
    23     cout << endl;
    24 
    25     return 0;
    26 }

    6. 下面我们来看一看list,如果vector好比是数组,那么list就像链表一样,这个容器我们用的比较少。 看看它有哪些操作

     1 #include <iostream>
     2 #include <string>
     3 #include <vector>
     4 #include <list>
     5 using namespace std;
     6 
     7 int main(int argc, const char *argv[])
     8 {
     9     list<string> lst;
    10     lst.push_back("beijing");
    11     lst.push_back("shanghai");
    12 
    13     lst.push_front("shenzhen");
    14 
    15     for(list<string>::const_iterator it = lst.begin();
    16         it != lst.end();
    17         ++it)
    18     {
    19         cout << *it << " ";
    20     }
    21 
    22     cout << endl;
    23     return 0;
    24 }

     list比vector 多出一个push_front成员函数,可以用于头插,把元素至于首POS。

    vector为存储的对象分配一块连续的地址空间,因此对vector中的元素随机访问效率很高。在vecotor中插入或者删除某个元素,需要将现有元素进行复制,移动。如果vector中存储的对象很大,或者构造函数复杂,则在对现有元素进行拷贝时开销较大,因为拷贝对象要调用拷贝构造函数。对于简单的小对象,vector的效率优于list。vector在每次扩张容量的时候,将容量扩展2倍,这样对于小对象来说,效率是很高的。

    list中的对象是离散存储的,随机访问某个元素需要遍历list。在list中插入元素,尤其是在首尾插入元素,效率很高,只需要改变元素的指针。

    综上所述:

    vector适用:对象数量变化少,简单对象,随机访问元素频繁

    list适用:对象数量变化大,对象复杂,插入和删除频

    vector 和 list 就好比 数组和链表一般, 一个是连续地址分布,一个是离散地址分布, 

    vector 可以高效 随机访问成员, 通过下标即可,但是插入和删除,需要移动其余的所以成员, 访问成员高效, 删除和插入低效

    list 是插入删除 成员高效, 但是访问低效 ,因为每次访问都需要遍历 list 就好像链表。

  • 相关阅读:
    测试
    python制作
    Mysql 用法
    Day006 Java面向对象编程
    Day005 Java数组详解
    Day004 Java方法详解
    Day003 Java流程控制
    Day002 Java基础语法
    Day001 MrakDown语法 Dos命令
    4. 谈谈你对ArrayList和LinkedList 的理解
  • 原文地址:https://www.cnblogs.com/DLzhang/p/3986841.html
Copyright © 2011-2022 走看看