精华内容
下载资源
问答
  • STL vector用法介绍+ STL 常用函数用法

    千次阅读 2016-07-20 20:23:44
    介绍 这篇文章的目的是为了介绍std::vector,...通过阅读这篇文章读者应该能够有效地使用vector容器,而且应该不会再去使用C类型的动态数组了。   Vector总览 vector是C++标准模板库中的部分内容,它是一个多功能

    介绍

    这篇文章的目的是为了介绍std::vector,如何恰当地使用它们的成员函数等操作。本文中还讨论了条件函数和函数指针在迭代算法中使用,如在remove_if()for_each()中的使用。通过阅读这篇文章读者应该能够有效地使用vector容器,而且应该不会再去使用C类型的动态数组了。

     

    Vector总览

    vectorC++标准模板库中的部分内容,它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库。vector之所以被认为是一个容器,是因为它能够像容器一样存放各种类型的对象,简单地说,vector是一个能够存放任意类型的动态数组,能够增加和压缩数据。

    为了可以使用vector,必须在你的头文件中包含下面的代码:

    #include <vector>

     

    vector属于std命名域的,因此需要通过命名限定,如下完成你的代码:

    using std::vector;

    vector<int> vInts;

     

    或者连在一起,使用全名:

    std::vector<int> vInts;

     

    建议使用全局的命名域方式:

    using namespace std;

     

    在后面的操作中全局的命名域方式会造成一些问题。vector容器提供了很多接口,在下面的表中列出vector的成员函数和操作。

     

    Vector成员函数

    函数

    表述

    c.assign(beg,end)

    c.assign(n,elem)

    [beg; end)区间中的数据赋值给c

    nelem的拷贝赋值给c

    c.at(idx)

    传回索引idx所指的数据,如果idx越界,抛出out_of_range

    c.back()

    传回最后一个数据,不检查这个数据是否存在。

    c.begin()

    传回迭代器重的可一个数据。

    c.capacity()

    返回容器中数据个数。

    c.clear()

    移除容器中所有数据。

    c.empty()

    判断容器是否为空。

    c.end()

    指向迭代器中的最后一个数据地址。

    c.erase(pos)

    c.erase(beg,end)

    删除pos位置的数据,传回下一个数据的位置。

    删除[beg,end)区间的数据,传回下一个数据的位置

    c.front()

    传回第一个数据。

    get_allocator

    使用构造函数返回一个拷贝。

    c.insert(pos,elem)

    c.insert(pos,n,elem)

    c.insert(pos,beg,end)

    pos位置插入一个elem拷贝,传回新数据位置。

    pos位置插入nelem数据。无返回值。

    pos位置插入在[beg,end)区间的数据。无返回值。

    c.max_size()

    返回容器中最大数据的数量。

    c.pop_back()

    删除最后一个数据。

    c.push_back(elem)

    在尾部加入一个数据。

    c.rbegin()

    传回一个逆向队列的第一个数据。

    c.rend()

    传回一个逆向队列的最后一个数据的下一个位置。

    c.resize(num)

    重新指定队列的长度。

    c.reserve()

    保留适当的容量。

    c.size()

    返回容器中实际数据的个数。

    c1.swap(c2)

    swap(c1,c2)

    c1c2元素互换。

    同上操作。

    vector<Elem> c

    vector <Elem> c1(c2)

    vector <Elem> c(n)

    vector <Elem> c(n, elem)

    vector <Elem> c(beg,end)

    c.~ vector <Elem>()

    创建一个空的vector

    复制一个vector

    创建一个vector,含有n个数据,数据均已缺省构造产生

    创建一个含有nelem拷贝的vector

    创建一个以[beg;end)区间的vector

    销毁所有数据,释放内存。

     

    Vector操作

    函数

    描述

    operator[]

    返回容器中指定位置的一个引用。

     

    创建一个vector

    vector容器提供了多种创建方法,下面介绍几种常用的。

    创建一个Widget类型的空的vector对象:

    vector<Widget> vWidgets;

    //     ------

    //      |

    //      |- Since vector is a Container, its member functions

    //         operate on iterators and the container itself so

    //         it can hold objects of any type.

     

    创建一个包含500Widget类型数据的vector

    vector<Widget> vWidgets(500);

     

    创建一个包含500Widget类型数据的vector,并且都初始化为0

    vector<Widget> vWidgets(500, Widget(0));

     

    创建一个Widget的拷贝:

    vector<Widget> vWidgetsFromAnother(vWidgets);

     

    vector添加一个数据

    vector添加数据的缺省方法是push_back()push_back()函数表示将数据添加到vector的尾部,并按需要来分配内存。例如:向vector<Widget>中添加10个数据,需要如下编写代码:

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

        vWidgets.push_back(Widget(i));

     

    获取vector中制定位置的数据

    很多时候我们不必要知道vector里面有多少数据,vector里面的数据是动态分配的,使用push_back()的一系列分配空间常常决定于文件或一些数据源。如果你想知道vector存放了多少数据,你可以使用empty()。获取vector的大小,可以使用size()。例如,如果你想获取一个vector v的大小,但不知道它是否为空,或者已经包含了数据,如果为空想设置为-1,你可以使用下面的代码实现:

    int nSize = v.empty() ? -1 : static_cast<int>(v.size());

     

    访问vector中的数据

    使用两种方法来访问vector

    1、   vector::at()

    2、   vector::operator[]

    operator[]主要是为了与C语言进行兼容。它可以像C语言数组一样操作。但at()是我们的首选,因为at()进行了边界检查,如果访问超过了vector的范围,将抛出一个例外。由于operator[]容易造成一些错误,所有我们很少用它,下面进行验证一下:

    分析下面的代码:

    vector<int> v;

    v.reserve(10);

     

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

        v.push_back(i);

     

    try

    {

     int iVal1 = v[7];  // not bounds checked - will not throw

     int iVal2 = v.at(7); // bounds checked - will throw if out of range

    }

    catch(const exception& e)

    {

     cout << e.what();

    }

     

    我们使用reserve()分配了10int型的空间,但并不没有初始化。 

    你可以在这个代码中尝试不同条件,观察它的结果,但是无论何时使用at(),都是正确的。

     

    删除vector中的数据

    vector能够非常容易地添加数据,也能很方便地取出数据,同样vector提供了erase()pop_back()clear()来删除数据,当你删除数据的时候,你应该知道要删除尾部的数据,或者是删除所有数据,还是个别的数据。在考虑删除等操作之前让我们静下来考虑一下在STL中的一些应用。

     

    Remove_if()算法

    现在我们考虑操作里面的数据。如果要使用remove_if(),我们需要在头文件中包含如下代码::

    #include <algorithm>

     

             Remove_if()有三个参数:

    1、   iterator _First:指向第一个数据的迭代指针。

    2、   iterator _Last:指向最后一个数据的迭代指针。

    3、   predicate _Pred:一个可以对迭代操作的条件函数。

     

    条件函数

    条件函数是一个按照用户定义的条件返回是或否的结果,是最基本的函数指针,或者是一个函数对象。这个函数对象需要支持所有的函数调用操作,重载operator()()操作。remove_if()是通过unary_function继承下来的,允许传递数据作为条件。

    例如,假如你想从一个vector<CString>中删除匹配的数据,如果字串中包含了一个值,从这个值开始,从这个值结束。首先你应该建立一个数据结构来包含这些数据,类似代码如下:

    #include <functional>

    enum findmodes

    {

     FM_INVALID = 0,

     FM_IS,

     FM_STARTSWITH,

     FM_ENDSWITH,

     FM_CONTAINS

    };

    typedef struct tagFindStr

    {

     UINT iMode;

     CString szMatchStr;

    } FindStr;

    typedef FindStr* LPFINDSTR;

     

    然后处理条件判断:

    class FindMatchingString

        : public std::unary_function<CString, bool>

    {

       

    public:

      FindMatchingString(const LPFINDSTR lpFS) : m_lpFS(lpFS) {}

       

      bool operator()(CString& szStringToCompare) const

      {

         bool retVal = false;

     

         switch(m_lpFS->iMode)

         {

         case FM_IS:

           {

             retVal = (szStringToCompare == m_lpFDD->szMatchStr);

             break;

           }

         case FM_STARTSWITH:

           {

             retVal = (szStringToCompare.Left(m_lpFDD->szMatchStr.GetLength())

                   == m_lpFDD->szWindowTitle);

             break;

           }

         case FM_ENDSWITH:

           {

             retVal = (szStringToCompare.Right(m_lpFDD->szMatchStr.GetLength())

                   == m_lpFDD->szMatchStr);

             break;

           }

         case FM_CONTAINS:

           {

             retVal = (szStringToCompare.Find(m_lpFDD->szMatchStr) != -1);

             break;

           }

         }

           

         return retVal;

     }

           

    private:

        LPFINDSTR m_lpFS;

    };

     

    通过这个操作你可以从vector中有效地删除数据:

    // remove all strings containing the value of

    // szRemove from vector<CString> vs.

     

    FindStr fs;

    fs.iMode = FM_CONTAINS;

    fs.szMatchStr = szRemove;

     

    vs.erase(std::remove_if(vs.begin(), vs.end(), FindMatchingString(&fs)), vs.end());

     

    Remove_if()能做什么?

    你可能会疑惑,对于上面那个例子在调用remove_if()的时候还要使用erase()呢?这是因为大家并不熟悉STL中的算法。Remove(),remove_if()等所有的移出操作都是建立在一个迭代范围上的,那么不能操作容器中的数据。所以在使用remove_if(),实际上操作的时容器里数据的上面的。思考上面的例子:

    1、   szRemove = “o”.

    2、   vs见下面图表中的显示。

    观察这个结果,我们可以看到remove_if()实际上是根据条件对迭代地址进行了修改,在数据的后面存在一些残余的数据,那些需要删除的数据。剩下的数据的位置可能不是原来的数据,但他们是不知道的。

    调用erase()来删除那些残余的数据。注意上面例子中通过erase()删除remove_if()的结果和vs.enc()范围的数据。

     

    压缩一个臃肿的vector

    很多时候大量的删除数据,或者通过使用reserve(),结果vector的空间远远大于实际需要的。所有需要压缩vector到它实际的大小。resize()能够增加vector的大小。Clear()仅仅能够改变缓存的大小,所有的这些对于vector释放内存等九非常重要了。如何来解决这些问题呢,让我们来操作一下。

    我们可以通过一个vector创建另一个vector。让我们看看这将发生什么。假定我们已经有一个vector v,它的内存大小为1000,当我们调用size()的时候,它的大小仅为7。我们浪费了大量的内存。让我们在它的基础上创建一个vector

    std::vector<CString> vNew(v);

    cout << vNew.capacity();

     

    vNew.capacity()返回的是7。这说明新创建的只是根据实际大小来分配的空间。现在我们不想释放v,因为我们要在其它地方用到它,我们可以使用swap()vvNew互相交换一下?

        vNew.swap(v);

        cout << vNew.capacity();

        cout << v.capacity();

     

    有趣的是:vNew.capacity()1000v.capacity()7

    现在是达到我的目的了,但是并不是很好的解决方法,我们可以像下面这么写:

        std::vector<CString>(v).swap(v);

         

    你可以看到我们做了什么?我们创建了一个临时变量代替那个命名的,然后使用swap(),这样我们就去掉了不必要的空间,得到实际大小的v

     

    结论

    我希望这个文档可以给那些使用STL vector容器的开发者很有价值的参考。我也希望通过阅读这篇文章你可以放心地使用vector来代替C语言中的数据了。

     

    ======================================================我是分割线============================================================


     迭代器(iterator)

      个人理解就是把所有和迭代有关的东西给抽象出来的,不管是数组的下标,指针,for里面的、list里面的、vector里面的,抽象一下变成了iterator

    复制代码
     1 #include <iostream>
     2 #include <vector>
     3 
     4 using namespace std;
     5 
     6 int main()
     7 {
     8     vector<int> v;
     9     for(int i = 0; i < 10; ++i )
    10     {
    11         v.push_back(i);
    12     }
    13     for(vector<int>::iterator it = v.begin(); it != v.end(); ++it)
    14     {
    15         cout << *it << " ";
    16     }
    17     cout << endl;
    18     return 0;
    19 }
    复制代码

      

      求和(<numeric> accumulate)

      accumulate(v.begin(),v.end(),0),把从 v.begin() 开始到 v.end()结束所有的元素加到 0上面去

    View Code

     

     

      vector(动态数组)

      vector有内存管理的机制,也就是说对于插入和删除,vector可以动态调整所占用的内存空间。  

      vector相关函数

    复制代码
     1 #include <iostream>
     2 #include <vector>
     3 
     4 using namespace std;
     5 
     6 int main()
     7 {
     8     vector<int> v;
     9     v.push_back(3);  //数组尾部插入3
    10     v.push_back(2);
    11     v.push_back(1);
    12     v.push_back(0);
    13     cout << " 下标 " << v[3] << endl;
    14     cout << " 迭代器 " << endl;
    15     for(vector<int>::iterator i = v.begin();i!= v.end();++i)
    16     {
    17         cout << *i << " ";
    18     }
    19     cout << endl;
    20     //在第一个元素之前插入111  insert begin+n是在第n个元素之前插入
    21     v.insert(v.begin(),111);
    22     //在最后一个元素之后插入222 insert end + n 是在n个元素之后插入
    23     v.insert(v.end(),222);
    24 
    25     for(vector<int>::iterator i = v.begin();i!= v.end();++i)
    26     {
    27         cout << *i << " ";
    28     }
    29     cout << endl;
    30 
    31     vector<int> arr(10);
    32     for(int i = 0; i < 10; i++)
    33     {
    34         arr[i] = i;
    35     }
    36     for(vector<int>::iterator i = arr.begin();i!= arr.end();++i)
    37     {
    38         cout << *i << " ";
    39     }
    40     cout << endl;
    41 
    42     //删除 同insert
    43     arr.erase(arr.begin());
    44 
    45     for(vector<int>::iterator i = arr.begin();i!= arr.end();++i)
    46      {
    47         cout << *i << " " ;
    48      }
    49     cout << endl ;
    50 
    51     arr.erase(arr.begin(),arr.begin()+5);
    52 
    53     for(vector<int>::iterator i = arr.begin();i!= arr.end();++i)
    54     {
    55         cout << *i << " " ;
    56     }
    57     cout << endl ;
    58     return 0 ;
    59  }
    复制代码

     


      数组转置 (<algorithm> reverse)

      reverse(v.begin(),v.end())

    复制代码
     1 #include<iostream>
     2 #include<vector>
     3 #include<algorithm>
     4 
     5 using namespace std;
     6 
     7 int main()
     8 {
     9     vector<int> v;
    10     for(int i = 0; i < 10; ++i)
    11     {
    12         v.push_back(i);
    13     }
    14     for(vector<int>::iterator it = v.begin(); it != v.end(); ++it)
    15     {
    16         cout << *it << " ";
    17     }
    18     cout << endl;
    19 
    20     reverse(v.begin(),v.end());
    21 
    22 
    23     for(vector<int>::iterator it = v.begin(); it != v.end(); ++it)
    24     {
    25         cout << *it << " ";
    26     }
    27     cout << endl;
    28     return 0;
    29 }
    复制代码

      排序(<algorithm> sort)

      sort(v.begin(),v.end())

    复制代码
     1 #include<iostream>
     2 #include<vector>
     3 #include<algorithm>
     4 
     5 using namespace std;
     6 
     7 bool Comp(const int &a,const int &b)
     8 {
     9     return a>b;
    10 }
    11 
    12 int main()
    13 {
    14     vector<int> v;
    15     v.push_back(1);
    16     v.push_back(3);
    17     v.push_back(2);
    18     v.push_back(55);
    19     v.push_back(-1);
    20     v.push_back(0);
    21     v.push_back(2);
    22     v.push_back(3);
    23     v.push_back(4);
    24 
    25     for(vector<int>::iterator it = v.begin(); it != v.end(); ++it)
    26     {
    27         cout << *it << " ";
    28     }
    29     cout << endl;
    30 
    31     //默认升序
    32     sort(v.begin(),v.end());
    33 
    34 
    35     for(vector<int>::iterator it = v.begin(); it != v.end(); ++it)
    36     {
    37         cout << *it << " ";
    38     }
    39     cout << endl;
    40 
    41     //用降序 需要自定义一个降序函数
    42     sort(v.begin(),v.end(),Comp);
    43 
    44 
    45     for(vector<int>::iterator it = v.begin(); it != v.end(); ++it)
    46     {
    47         cout << *it << " ";
    48     }
    49     cout << endl;
    50 
    51     return 0;
    52 }
    复制代码

      字符串(<string>)

      输入

    复制代码
     1 #include<iostream>
     2 #include<string>
     3 #include<cstdio>
     4 
     5 using namespace std;
     6 
     7 int main()
     8 {
     9     string s1;
    10     s1 = "hello";
    11 
    12     string s2;
    13     char s[1024];
    14     //scanf 输入速度比cin快的多
    15     //scanf 是C函数,不可以输入string
    16     scanf("%s",s);
    17     s2 = s;
    18 
    19     cout << s1 << endl;
    20     cout << s2 << endl;
    21 
    22     return 0;
    23 }
    复制代码

     

      尾部添加字符字符串直接用+号 例如: s += 'a'; s += "abc",或者使用append方法,s.append(“123”)

      删除 (erase clear)

      s.erase(it + 1,it + 4); clear()

    复制代码
     1 #include<iostream>
     2 #include<string>
     3 
     4 using namespace std;
     5 
     6 int main()
     7 {
     8     string s;
     9     s = "0123456789";
    10     cout << s << endl;
    11 
    12     string::iterator it = s.begin();
    13 
    14     //删除s[3]
    15     s.erase(it+3);
    16     cout << s << endl;
    17 
    18     //删除s[1]~s[3]
    19     s = "0123456789";
    20     s.erase(it + 1,it + 4);
    21     cout << s << endl;
    22 
    23     //全部删除
    24     s.clear();
    25     cout << "clear : " << s << endl;
    26 
    27     return 0;
    28 }
    复制代码

      查找(find)

      用find找到string里面第一个要找到元素(char或者串),找到返回数组下标,找不到返回end()迭代器

      string和vector有很多相同的东西,比如length(),size(),empty(),reverse(),相对也容易,就不一一说了。

      数字化处理(string)

      经常会遇到这样一种情况,有一个数字,需要把每一位给提取出来,如果用取余数的方法,花费的时间就会很长,所以可以当成字符串来处理,方便、省时。

      例子:求一个整数各位数的和

    复制代码
     1 #include<iostream>
     2 #include<string>
     3 
     4 using namespace std;
     5 
     6 int main()
     7 {
     8     string s;
     9     s = "123456789";
    10     int sum = 0;
    11     for(int i = 0; i < s.size(); ++i)
    12     {
    13         switch(s[i])
    14         {
    15             case '1': sum += 1;break;
    16             case '2': sum += 2;break;
    17             case '3': sum += 3;break;
    18             case '4': sum += 4;break;
    19             case '5': sum += 5;break;
    20             case '6': sum += 6;break;
    21             case '7': sum += 7;break;
    22             case '8': sum += 8;break;
    23             case '9': sum += 9;break;
    24         }
    25     }
    26     
    27     cout << sum << endl;
    28     
    29     return 0;
    30 }
    复制代码

      string与char *

      

    View Code

      sscanf

      

    View Code

      string与数值相互转换( sprintf <sstream> )

    复制代码
     1 #include<iostream>
     2 #include<string>
     3 #include<sstream>
     4 #include<cstdio>
     5 
     6 using namespace std;
     7 
     8 //c++ 方法 把数转换为string
     9 string converToString(double x)
    10 {
    11     ostringstream o;
    12     if( o << x)
    13     {
    14         // str()没有'\0' c_str有
    15         return o.str();
    16     }
    17     return "error";
    18 }
    19 
    20 double converFromString(const string &s)
    21 {
    22     istringstream i(s);
    23     double x;
    24     if( i >> x)
    25     {
    26         return x;
    27     }
    28     //if error
    29     return 0.0;
    30 }
    31 int main()
    32 {
    33     char b[100];
    34     string s1;
    35 
    36     //c语言方法
    37     sprintf(b,"%d",1987);
    38     s1 = b;
    39     cout << s1 << endl;
    40 
    41     string s2 = converToString(1954);
    42     cout << s2 << endl;
    43 
    44     string s3 = "202";
    45     int c = converFromString(s3);
    46     cout << c << endl;
    47 
    48     string s4 = "casacsa6";
    49     int d = converFromString(s4);
    50     cout << d << endl;
    51 
    52     string s5 = "21abf4";
    53     int f = converFromString(s5);
    54     cout << f << endl;
    55 
    56     return 0;
    57 }
    复制代码

     

      set容器

      set是用红黑树的平衡二叉索引树的数据结构来实现的,插入时,它会自动调节二叉树排列,把元素放到适合的位置,确保每个子树根节点的键值大于左子树所有的值、小于右子树所有的值,插入重复数据时会忽略。set迭代器采用中序遍历,检索效率高于vector、deque、list,并且会将元素按照升序的序列遍历。set容器中的数值,一经更改,set会根据新值旋转二叉树,以保证平衡,构建set就是为了快速检索(python中的set一旦建立就是一个常量,不能改的)。

      multiset,与set不同之处就是它允许有重复的键值。

      正反遍历,迭代器iterator、reverse_iterator

    复制代码
     1 #include<iostream>
     2 #include<set>
     3 
     4 using namespace std;
     5 
     6 int main()
     7 {
     8     set<int> v;
     9     v.insert(1);
    10     v.insert(3);
    11     v.insert(5);
    12     v.insert(2);
    13     v.insert(4);
    14     v.insert(3);
    15 
    16     //中序遍历 升序遍历
    17     for(set<int>::iterator it = v.begin(); it != v.end(); ++it)
    18     {
    19         cout << *it << " ";
    20     }
    21     cout << endl;
    22 
    23     for(set<int>::reverse_iterator rit = v.rbegin(); rit != v.rend(); ++rit)
    24     {
    25         cout << *rit << " ";
    26     }
    27     cout << endl;
    28 
    29     return 0;
    30 }
    复制代码

      自定义比较函数,insert的时候,set会使用默认的比较函数(升序),很多情况下需要自己编写比较函数。

      1、如果元素不是结构体,可以编写比较函数,下面这个例子是用降序排列的(和上例插入数据相同):

    复制代码
     1 #include<iostream>
     2 #include<set>
     3 
     4 using namespace std;
     5 
     6 struct Comp
     7 {
     8     //重载()
     9     bool operator()(const int &a, const int &b)
    10     {
    11         return a > b;
    12     }
    13 };
    14 int main()
    15 {
    16     set<int,Comp> v;
    17     v.insert(1);
    18     v.insert(3);
    19     v.insert(5);
    20     v.insert(2);
    21     v.insert(4);
    22     v.insert(3);
    23   
    24     for(set<int,Comp>::iterator it = v.begin(); it != v.end(); ++it)
    25     {
    26         cout << *it << " ";
    27     }
    28     cout << endl;
    29 
    30     for(set<int,Comp>::reverse_iterator rit = v.rbegin(); rit != v.rend(); ++rit)
    31     {
    32         cout << *rit << " ";
    33     }
    34     cout << endl;
    35 
    36     return 0;
    37 }
    复制代码

     

      2、元素本身就是结构体,直接把比较函数写在结构体内部,下面的例子依然降序:

    复制代码
     1 #include<iostream>
     2 #include<set>
     3 #include<string>
     4 
     5 using namespace std;
     6 
     7 struct Info
     8 {
     9     string name;
    10     double score;
    11 
    12     //重载 <
    13     bool operator < (const Info &a) const
    14     {
    15         return a.score < score;
    16     }
    17 };
    18 int main()
    19 {
    20     set<Info> s;
    21     Info info;
    22 
    23     info.name = "abc";
    24     info.score = 123.3;
    25     s.insert(info);
    26 
    27     info.name = "EDF";
    28     info.score = -23.53;
    29     s.insert(info);
    30 
    31 
    32     info.name = "xyz";
    33     info.score = 73.3;
    34     s.insert(info);
    35     
    36     for(set<Info>::iterator it = s.begin(); it != s.end(); ++it)
    37     {
    38         cout << (*it).name << ":" << (*it).score << endl;
    39     }
    40     cout << endl;
    41 
    42     for(set<Info>::reverse_iterator rit = s.rbegin(); rit != s.rend(); ++rit)
    43     {
    44         cout << (*rit).name << ":" << (*rit).score << endl;
    45     }
    46     cout << endl;
    47 
    48     return 0;
    49 }
    复制代码

      multiset与set的不同之处就是key可以重复,以及erase(key)的时候会删除multiset里面所有的key并且返回删除的个数。

      map

      map也是使用红黑树,他是一个键值对(key:value映射),便利时依然默认按照key程序的方式遍历,同set。

    复制代码
     1 #include<iostream>
     2 #include<map>
     3 #include<string>
     4 
     5 using namespace std;
     6 
     7 int main()
     8 {
     9     map<string,double> m;
    10 
    11     //声明即插入
    12     m["li"] = 123.4;
    13     m["wang"] = 23.1;
    14     m["zhang"] = -21.9;
    15     m["abc"] = 12.1;
    16     for(map<string,double>::iterator it = m.begin(); it != m.end(); ++it)
    17     {
    18         //first --> key second --> value
    19         cout << (*it).first << ":" << (*it).second << endl;
    20     }
    21     cout << endl;
    22     return 0;
    23 }
    复制代码

      用map实现数字分离

      string --> number

      之前用string进行过数字分离,现在使用map

    复制代码
     1 #include<iostream>
     2 #include<map>
     3 #include<string>
     4 
     5 using namespace std;
     6 
     7 int main()
     8 {
     9     map<char,int> m;
    10 
    11     m['0'] = 0;
    12     m['1'] = 1;
    13     m['2'] = 2;
    14     m['3'] = 3;
    15     m['4'] = 4;
    16     m['5'] = 5;
    17     m['6'] = 6;
    18     m['7'] = 7;
    19     m['8'] = 8;
    20     m['9'] = 9;
    21     /*
    22         等价于
    23         for(int i = 0; i < 10; ++i)
    24         {
    25             m['0' + i] = i;
    26         }
    27     */
    28 
    29     string sa;
    30     sa = "9876543210";
    31     int sum = 0;
    32     for( int i = 0; i < sa.length(); ++i)
    33     {
    34         sum += m[sa[i]];
    35     }
    36     cout << sum << endl;
    37     return 0;
    38 }
    复制代码

      number --> string

    复制代码
     1 #include <iostream>
     2 #include <map>
     3 #include <string>
     4 
     5 using namespace std;
     6 
     7 int main()
     8 {
     9     map<int,char> m;
    10 
    11     for(int i = 0; i < 10; ++i)
    12     {
    13         m[i] = '0' + i;
    14     }
    15 
    16     int n = 7;
    17 
    18     string out = "the number is :";
    19     cout << out + m[n] << endl;
    20 
    21     return 0;
    22 }
    复制代码

      multimap

      multimap由于允许有重复的元素,所以元素插入、删除、查找都与map不同。

      插入insert(pair<a,b>(value1,value2))

    复制代码
     1 #include <iostream>
     2 #include <map>
     3 #include <string>
     4 
     5 using namespace std;
     6 
     7 int main()
     8 {
     9     multimap<string,double> m;
    10 
    11     m.insert(pair<string,double>("Abc",123.2));
    12     m.insert(pair<string,double>("Abc",123.2));
    13     m.insert(pair<string,double>("xyz",-43.2));
    14     m.insert(pair<string,double>("dew",43.2));
    15 
    16     for(multimap<string,double>::iterator it = m.begin(); it != m.end(); ++it )
    17     {
    18         cout << (*it).first << ":" << (*it).second << endl;
    19     }
    20     cout << endl;
    21 
    22     return 0;
    23 }
    复制代码

      至于删除和查找,erase(key)会删除掉所有key的map,查找find(key)返回第一个key的迭代器

      deque

      deque和vector一样,采用线性表,与vector唯一不同的是,deque采用的分块的线性存储结构,每块大小一般为512字节,称为一个deque块,所有的deque块使用一个Map块进行管理,每个map数据项记录各个deque块的首地址,这样以来,deque块在头部和尾部都可已插入和删除元素,而不需要移动其它元素。使用push_back()方法在尾部插入元素,使用push_front()方法在首部插入元素,使用insert()方法在中间插入元素。一般来说,当考虑容器元素的内存分配策略和操作的性能时,deque相对vectore更有优势。(下面这个图,我感觉Map块就是一个list< map<deque名字,deque地址> >)

      插入删除

      遍历当然可以使用下标遍历,在这里使用迭代器。

    复制代码
     1 #include <iostream>
     2 #include <deque>
     3 
     4 using namespace std;
     5 
     6 int main()
     7 {
     8     deque<int> d;
     9 
    10     //尾部插入
    11     d.push_back(1);
    12     d.push_back(3);
    13     d.push_back(2);
    14     for(deque<int>::iterator it = d.begin(); it != d.end(); ++it )
    15     {
    16         cout << (*it) << " ";
    17     }
    18     cout << endl << endl;
    19 
    20     //头部插入
    21     d.push_front(10);
    22     d.push_front(-23);
    23     for(deque<int>::iterator it = d.begin(); it != d.end(); ++it )
    24     {
    25         cout << (*it) << " ";
    26     }
    27     cout << endl << endl;
    28 
    29     d.insert(d.begin() + 2,9999);
    30     for(deque<int>::iterator it = d.begin(); it != d.end(); ++it )
    31     {
    32         cout << (*it) << " ";
    33     }
    34     cout << endl << endl;
    35 
    36     //反方向遍历
    37     for(deque<int>::reverse_iterator rit = d.rbegin(); rit != d.rend(); ++rit )
    38     {
    39         cout << (*rit) << " ";
    40     }
    41     cout << endl << endl;
    42 
    43     //删除元素pop pop_front从头部删除元素 pop_back从尾部删除元素 erase中间删除 clear全删
    44     d.clear();
    45     d.push_back(1);
    46     d.push_back(2);
    47     d.push_back(3);
    48     d.push_back(4);
    49     d.push_back(5);
    50     d.push_back(6);
    51     d.push_back(7);
    52     d.push_back(8);
    53     for(deque<int>::iterator it = d.begin(); it != d.end(); ++it )
    54     {
    55         cout << (*it) << " ";
    56     }
    57     cout << endl;
    58 
    59     d.pop_front();
    60     d.pop_front();
    61     for(deque<int>::iterator it = d.begin(); it != d.end(); ++it )
    62     {
    63         cout << (*it) << " ";
    64     }
    65     cout << endl;
    66 
    67     d.pop_back();
    68     d.pop_back();
    69     for(deque<int>::iterator it = d.begin(); it != d.end(); ++it )
    70     {
    71         cout << (*it) << " ";
    72     }
    73     cout << endl;
    74 
    75     d.erase(d.begin() + 1);
    76     for(deque<int>::iterator it = d.begin(); it != d.end(); ++it )
    77     {
    78         cout << (*it) << " ";
    79     }
    80     cout << endl;
    81     return 0;
    82 }
    复制代码

      list

      list<int> l

      插入:push_back尾部,push_front头部,insert方法前往迭代器位置处插入元素,链表自动扩张,迭代器只能使用++--操作,不能用+n -n,因为元素不是物理相连的。

      遍历:iterator和reverse_iterator正反遍历

      删除:pop_front删除链表首元素;pop_back()删除链表尾部元素;erase(迭代器)删除迭代器位置的元素,注意只能使用++--到达想删除的位置;remove(key) 删除链表中所有key的元素,clear()清空链表。

      查找:it = find(l.begin(),l.end(),key)

      排序:l.sort()

      删除连续重复元素:l.unique() 【2 8 1 1 1 5 1】 --> 【 2 8 1 5 1】

      bitset

      从来没用过,上两幅图吧就:

      stack(后进先出)

      这个印象深刻,学数据结构的时候做表达式求值的就是用的栈。

    复制代码
     1 #include <iostream>
     2 #include <stack>
     3 using namespace std;
     4 
     5 int main()
     6 {
     7 
     8     stack<int> s;
     9     s.push(1);
    10     s.push(2);
    11     s.push(4);
    12     s.push(5);
    13 
    14     cout << s.size() << endl;
    15 
    16     while(s.empty() != true)
    17     {
    18         cout << s.top() << endl;
    19         s.pop();
    20     }
    21     return 0;
    22 }
    复制代码

     

      stack然我唯一费解之处在于,貌似它没有iterator,可以试试s.begin()编译器报错的。

      queue(先进先出)

      queue有入队push(插入)、出队pop(删除)、读取队首元素front、读取队尾元素back、empty,size这几种方法

      priority_queue(最大元素先出)

     

     

     

    复制代码
     1 #include <iostream>
     2 #include <queue>
     3 using namespace std;
     4 
     5 int main()
     6 {
     7 
     8     priority_queue<int> pq;
     9 
    10     pq.push(1);
    11     pq.push(3);
    12     pq.push(2);
    13     pq.push(8);
    14     pq.push(9);
    15     pq.push(0);
    16 
    17     cout << "size: " << pq.size() << endl;
    18 
    19     while(pq.empty() != true)
    20     {
    21         cout << pq.top() << endl;
    22         pq.pop();
    23     }
    24     return 0;
    25 }
    复制代码

      重载操作符同set重载操作符。


    展开全文
  • c ++ string.find() 用法

    千次阅读 2018-03-18 16:37:11
    #include&lt;iostream&gt; #include&lt;cstring&gt; #include&...vector&gt; #include&lt;set&gt; #include&lt;map&gt; #include&lt;queue&gt; #include&
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<set>
    #include<map>
    #include<queue>
    #include<cmath>
    using namespace std;
    
    int main()
    {
        string s;
        string s1;
        cin>>s>>s1;
        s.find(s1);//返回s1在s中的位置,没找到返回-1
        s.find_first_of(s1);//返回任意字符s1在s中第一次出现的位置,s1是字符不可以为字符串
        s.find(s1, a);//从s下标为a开始查找字符串s1,返回起始位置,找不到返回-1
        
        
        
        
       string s="abb abb abb";  //查找字符s1在s中出现的所有起始位置
       string s1="a"; //char s1='a';  
       int position=0;  
       int i=0;  
       while((position=s.find_first_of(s1,position))!=string::npos)  
       {  
           cout<<position<<endl;  
           position++;  
           i++;//i为出现的总次数  
       }  
       cout<<"total="<<i<<endl;  
       /*0
         4 
         8 
         total = 3 
       */
       
       
       
       string s="aaabcd";  //查找s1与s第一次出现不符合的位置
       string s1="aaafcd";  
       int position;  
       position=s.find_first_not_of(s1);  
       cout<<position<<endl;
       /*
         3 
       */
       
       
       
       string str ("The sixth sick sheik's sixth sheep's sick.");
       string key ("sixth");
       size_t found;
       int found = str.rfind(key); //由于是rfind, 所以得到的是后面的sixth的位置, 如果使用find, 得到的就是前一个sixth的位置
       return 0;  
    }
    

    展开全文
  • 该库为c ++容器提供基本SQL语句功能(或基本的C#LINQ方法),即: Where , Update , Distinct , OrderBy , GroupBy和Join 。 另外还有WhereLazy和DistinctLazy ,它们分别是Where和Distinct惰性版本。 支持的...
  • FTL是基于C ++ 17的库,为集合处理提供了更方便的API。 该API在很大程度上受Rust编程语言的启发。 基本用法 使用FTL进行收集处理非常容易。 在下面,您可以找到一个简单的示例,介绍FTL的功能。 struct Tree { ...
  • C ++三次样条插值 这是三次样条的轻量级实现,可以通过以下特征对点f(x i )= y i进行插值。 可用的样条线类型: 三次C 2样条曲线:全局,两次连续可微分 三次Hermite花键:局部,连续可微(C 1 ) 边界条件:...
  • C ++中基于窗口的相机库。 特征 使用OpenCV :: Mat 支持相机分辨率设置 支持相机属性设置 支持曝光融合 循环程序来处理相机循环 目录 用法 # include using namespace DirectShowCamera ; // Get a empty camera ...
  • 一个C ++ 11仅限标头的库,用于验证嵌入式设备上的文件。 该库用于验证DfuSe文件,而不必将完整的映像保存在RAM中。 取而代之的是,仅保存图像的偏移量,以便于提取和复制到例如Flash。 可以使用生成DfuSe图像。 ...
  • 这是一堆将Keras神经网络模型移植到纯C ++中的代码。 神经网络权重和体系结构存储在纯文本文件中,对于图像,输入表示为vector<vector> > > 。 该代码准备支持简单的卷积网络(以MNIST为例),但可以轻松扩展。 仅...
  • C++Vector用法

    2014-05-04 11:50:50
    vectorc++stringiteratorinserttransformation C++内置的数组支持容器的机制,但是它不支持容器抽象的语义。要解决此问题我们自己实现这样的类。在标准C++中,用容器向量(vector)实现。容器向量也是一个类

    C++Vector用法

    分类: C/C++ 65127人阅读 评论(5) 收藏 举报

    C++内置的数组支持容器的机制,但是它不支持容器抽象的语义。要解决此问题我们自己实现这样的类。在标准C++中,用容器向量(vector)实现。容器向量也是一个类模板。
    标准库vector类型使用需要的头文件:#include <vector>。vector 是一个类模板。不是一种数据类型,vector<int>是一种数据类型。Vector的存储空间是连续的,list不是连续存储的。

    一、 定义和初始化
    vector< typeName > v1;       //默认v1为空,故下面的赋值是错误的v1[0]=5;
    vector<typeName>v2(v1); 或v2=v1;或vector<typeName> v2(v1.begin(), v1.end());//v2是v1的一个副本,若v1.size()>v2.size()则赋值后v2.size()被扩充为v1.size()。
    vector< typeName > v3(n,i);//v3包含n个值为i的typeName类型元素
    vector< typeName > v4(n); //v4含有n个值为0的元素
    int a[4]={0,1,2,3,3}; vector<int> v5(a,a+5);//v5的size为5,v5被初始化为a的5个值。后一个指针要指向将被拷贝的末元素的下一位置。
    vector<int> v6(v5);//v6是v5的拷贝
    vector< 类型 > 标识符(最大容量,初始所有值);

     

    二、 值初始化
    1>     如果没有指定元素初始化式,标准库自行提供一个初始化值进行值初始化。
    2>     如果保存的式含有构造函数的类类型的元素,标准库使用该类型的构造函数初始化。
    3>     如果保存的式没有构造函数的类类型的元素,标准库产生一个带初始值的对象,使用这个对象进行值初始化。


    三、vector对象最重要的几种操作
    1. v.push_back(t)    在容器的最后添加一个值为t的数据,容器的size变大。
        另外list有push_front()函数,在前端插入,后面的元素下标依次增大。
    2. v.size()        返回容器中数据的个数,size返回相应vector类定义的size_type的值。v.resize(2*v.size)或                  

    v.resize(2*v.size, 99) 将v的容量翻倍(并把新元素的值初始化为99)
    3. v.empty()     判断vector是否为空
    4. v[n]           返回v中位置为n的元素
    5. v.insert(pointer,number, content)    向v中pointer指向的位置插入number个content的内容。
        还有v. insert(pointer, content),v.insert(pointer,a[2],a[4])将a[2]到a[4]三个元素插入。
    6. v.pop_back()    删除容器的末元素,并不返回该元素。
    7.v.erase(pointer1,pointer2) 删除pointer1到pointer2中间(包括pointer1所指)的元素。
       vector中删除一个元素后,此位置以后的元素都需要往前移动一个位置,虽然当前迭代器位置没有自动加1,
       但是由于后续元素的顺次前移,也就相当于迭代器的自动指向下一个位置一样。
    8. v1==v2          判断v1与v2是否相等。
    9. !=、<、<=、>、>=      保持这些操作符惯有含义。
    10. vector<typeName>::iterator p=v1.begin( ); p初始值指向v1的第一个元素。*p取所指向元素的值。
          对于const vector<typeName>只能用vector<typeName>::const_iterator类型的指针访问。
    11.   p=v1.end( ); p指向v1的最后一个元素的下一位置。
    12.v.clear()      删除容器中的所有元素。12.v.clear()      删除容器中的所有元素。

    #include<algorithm>中的泛函算法
    搜索算法:find() 、search() 、count() 、find_if() 、search_if() 、count_if()
    分类排序:sort() 、merge()
    删除算法:unique() 、remove()
    生成和变异:generate() 、fill() 、transformation() 、copy()
    关系算法:equal() 、min() 、max()
    sort(v1.begin(),vi.begin()+v1.size/2); 对v1的前半段元素排序
    list<char>::iterator pMiddle =find(cList.begin(),cList.end(),'A');找到则返回被查内容第一次出现处指针,否则返回end()。
    vector< typeName >::size_type x ; vector< typeName >类型的计数,可用于循环如同for(int i)


    初学C++的程序员可能会认为vector的下标操作可以添加元素,其实不然:

    vector<int> ivec;   // empty vector

    for (vector<int>::size_type ix = 0; ix != 10; ++ix)

         ivec[ix] = ix; // disaster: ivec has no elements

    上述程序试图在ivec中插入10个新元素,元素值依次为0到9的整数。但是,这里ivec是空的vector对象,而且下标只能用于获取已存在的元素。

    这个循环的正确写法应该是:

    for (vector<int>::size_type ix = 0; ix != 10; ++ix)

         ivec.push_back(ix); // ok: adds new element with value ix


    警告:必须是已存在的元素才能用下标操作符进行索引。通过下标操作进行赋值时,不会添加任何元素。仅能对确知已存在的元素进行下标操作 

      

    四、内存管理与效率

          1.使用reserve()函数提前设定容量大小,避免多次容量扩充操作导致效率低下。

          关于STL容器,最令人称赞的特性之一就是是只要不超过它们的最大大小,它们就可以自动增长到足以容纳你放进去的数据。(要知道这个最大值,只要调用名叫max_size的成员函数。)对于vector和string,如果需要更多空间,就以类似realloc的思想来增长大小。vector容器支持随机访问,因此为了提高效率,它内部使用动态数组的方式实现的。在通过 reserve() 来申请特定大小的时候总是按指数边界来增大其内部缓冲区。当进行insert或push_back等增加元素的操作时,如果此时动态数组的内存不够用,就要动态的重新分配当前大小的1.5~2倍的新内存区,再把原数组的内容复制过去。所以,在一般情况下,其访问速度同一般数组,只有在重新分配发生时,其性能才会下降。正如上面的代码告诉你的那样。而进行pop_back操作时,capacity并不会因为vector容器里的元素减少而有所下降,还会维持操作之前的大小。对于vector容器来说,如果有大量的数据需要进行push_back,应当使用reserve()函数提前设定其容量大小,否则会出现许多次容量扩充操作,导致效率低下。

          reserve成员函数允许你最小化必须进行的重新分配的次数,因而可以避免真分配的开销和迭代器/指针/引用失效。但在我解释reserve为什么可以那么做之前,让我简要介绍有时候令人困惑的四个相关成员函数。在标准容器中,只有vector和string提供了所有这些函数。

    (1) size()告诉你容器中有多少元素。它没有告诉你容器为它容纳的元素分配了多少内存。
    (2) capacity()告诉你容器在它已经分配的内存中可以容纳多少元素。那是容器在那块内存中总共可以容纳多少元素,而不是还可以容纳多少元素。如果你想知道一个vector或string中有多少没有被占用的内存,你必须从capacity()中减去size()。如果size和capacity返回同样的值,容器中就没有剩余空间了,而下一次插入(通过insert或push_back等)会引发上面的重新分配步骤。
    (3) resize(Container::size_type n)强制把容器改为容纳n个元素。调用resize之后,size将会返回n。如果n小于当前大小,容器尾部的元素会被销毁。如果n大于当前大小,新默认构造的元素会添加到容器尾部。如果n大于当前容量,在元素加入之前会发生重新分配。
    (4) reserve(Container::size_type n)强制容器把它的容量改为至少n,提供的n不小于当前大小。这一般强迫进行一次重新分配,因为容量需要增加。(如果n小于当前容量,vector忽略它,这个调用什么都不做,string可能把它的容量减少为size()和n中大的数,但string的大小没有改变。在我的经验中,使用reserve来从一个string中修整多余容量一般不如使用“交换技巧”,那是条款17的主题。)

         这个简介表示了只要有元素需要插入而且容器的容量不足时就会发生重新分配(包括它们维护的原始内存分配和回收,对象的拷贝和析构和迭代器、指针和引用的失效)。所以,避免重新分配的关键是使用reserve尽快把容器的容量设置为足够大,最好在容器被构造之后立刻进行。

    例如,假定你想建立一个容纳1-1000值的vector<int>。没有使用reserve,你可以像这样来做:

    vector<int> v;
    for (int i = 1; i <= 1000; ++i) v.push_back(i);
    在大多数STL实现中,这段代码在循环过程中将会导致2到10次重新分配。(10这个数没什么奇怪的。记住vector在重新分配发生时一般把容量翻倍,而1000约等于210。)

    把代码改为使用reserve,我们得到这个:

    vector<int> v;
    v.reserve(1000);
    for (int i = 1; i <= 1000; ++i) v.push_back(i);
    这在循环中不会发生重新分配。

    在大小和容量之间的关系让我们可以预言什么时候插入将引起vector或string执行重新分配,而且,可以预言什么时候插入会使指向容器中的迭代器、指针和引用失效。例如,给出这段代码,

    string s;
    ...
    if (s.size() < s.capacity()) {
    s.push_back('x');
    }
    push_back的调用不会使指向这个string中的迭代器、指针或引用失效,因为string的容量保证大于它的大小。如果不是执行push_back,代码在string的任意位置进行一个insert,我们仍然可以保证在插入期间没有发生重新分配,但是,与伴随string插入时迭代器失效的一般规则一致,所有从插入位置到string结尾的迭代器/指针/引用将失效。

    回到本条款的主旨,通常有两情况使用reserve来避免不必要的重新分配。第一个可用的情况是当你确切或者大约知道有多少元素将最后出现在容器中。那样的话,就像上面的vector代码,你只是提前reserve适当数量的空间。第二种情况是保留你可能需要的最大的空间,然后,一旦你添加完全部数据,修整掉任何多余的容量。

           2.使用“交换技巧”来修整vector过剩空间/内存

          有一种方法来把它从曾经最大的容量减少到它现在需要的容量。这样减少容量的方法常常被称为“收缩到合适(shrink to fit)”。该方法只需一条语句:vector<int>(ivec).swap(ivec);
    表达式vector<int>(ivec)建立一个临时vector,它是ivec的一份拷贝:vector的拷贝构造函数做了这个工作。但是,vector的拷贝构造函数只分配拷贝的元素需要的内存,所以这个临时vector没有多余的容量。然后我们让临时vector和ivec交换数据,这时我们完成了,ivec只有临时变量的修整过的容量,而这个临时变量则持有了曾经在ivec中的没用到的过剩容量。在这里(这个语句结尾),临时vector被销毁,因此释放了以前ivec使用的内存,收缩到合适。

         3.用swap方法强行释放STL Vector所占内存

    template < class T> void ClearVector( vector<T>& v )
    {
        vector<T>vtTemp;
        vtTemp.swap( v );
    }

        vector<int> v ;
        nums.push_back(1);
        nums.push_back(3);
        nums.push_back(2);
        nums.push_back(4);
        vector<int>().swap(v);

    /* 或者v.swap(vector<int>()); */

    /*或者{ std::vector<int> tmp = v;   v.swap(tmp);   }; //加大括号{ }是让tmp退出{ }时自动析构*/

     

    五、Vector 内存管理成员函数的行为测试
    C++ STL的vector使用非常广泛,但是对其内存的管理模型一直有多种猜测,下面用实例代码测试来了解其内存管理方式,测试代码如下:

    #include <iostream>
    #include <vector>
    using namespace std;

    int main()
    {
    vector<int> iVec;
    cout << "容器 大小为: " << iVec.size() << endl;
    cout << "容器 容量为: " << iVec.capacity() << endl; //1个元素, 容器容量为1

    iVec.push_back(1);
    cout << "容器 大小为: " << iVec.size() << endl;
    cout << "容器 容量为: " << iVec.capacity() << endl; //2个元素, 容器容量为2

    iVec.push_back(2);
    cout << "容器 大小为: " << iVec.size() << endl;
    cout << "容器 容量为: " << iVec.capacity() << endl; //3个元素, 容器容量为4

    iVec.push_back(3);
    cout << "容器 大小为: " << iVec.size() << endl;
    cout << "容器 容量为: " << iVec.capacity() << endl; //4个元素, 容器容量为4

    iVec.push_back(4);
    iVec.push_back(5);
    cout << "容器 大小为: " << iVec.size() << endl;
    cout << "容器 容量为: " << iVec.capacity() << endl; //5个元素, 容器容量为8

    iVec.push_back(6);
    cout << "容器 大小为: " << iVec.size() << endl;
    cout << "容器 容量为: " << iVec.capacity() << endl; //6个元素, 容器容量为8

    iVec.push_back(7);
    cout << "容器 大小为: " << iVec.size() << endl;
    cout << "容器 容量为: " << iVec.capacity() << endl; //7个元素, 容器容量为8

    iVec.push_back(8);
    cout << "容器 大小为: " << iVec.size() << endl;
    cout << "容器 容量为: " << iVec.capacity() << endl; //8个元素, 容器容量为8

    iVec.push_back(9);
    cout << "容器 大小为: " << iVec.size() << endl;
    cout << "容器 容量为: " << iVec.capacity() << endl; //9个元素, 容器容量为16
    /* vs2005/8 容量增长不是翻倍的,如
        9个元素   容量9
        10个元素 容量13 */

    /* 测试effective stl中的特殊的交换 swap() */
    cout << "当前vector 的大小为: " << iVec.size() << endl;
    cout << "当前vector 的容量为: " << iVec.capacity() << endl;
    vector<int>(iVec).swap(iVec);

    cout << "临时的vector<int>对象 的大小为: " << (vector<int>(iVec)).size() << endl;
    cout << "临时的vector<int>对象 的容量为: " << (vector<int>(iVec)).capacity() << endl;
    cout << "交换后,当前vector 的大小为: " << iVec.size() << endl;
    cout << "交换后,当前vector 的容量为: " << iVec.capacity() << endl;

    return 0;
    }

     

     六、vector的其他成员函数

    c.assign(beg,end)
    将[beg; end)区间中的数据赋值给c。
    c.assign(n,elem)
    将n个elem的拷贝赋值给c。
    c.at(idx)
    传回索引idx所指的数据,如果idx越界,抛出out_of_range。
    c.back()
    传回最后一个数据,不检查这个数据是否存在。
    c.front()
    传回地一个数据。
    get_allocator
    使用构造函数返回一个拷贝。
    c.rbegin()
    传回一个逆向队列的第一个数据。
    c.rend()
    传回一个逆向队列的最后一个数据的下一个位置。
    c.~ vector <Elem>()
    销毁所有数据,释放内存
    展开全文
  • vector详细用法

    2012-12-30 19:00:16
    vectorc++iterator数据结构exceptionalgorithm vector是C++标准模板库中的部分内容,它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库。vector之所以被认为是一个容器,是因为它能够像容器一样存放...
  • c++中vector用法详解

    千次阅读 2017-06-01 10:50:23
    【活动】2017 CSDN博客专栏评选 【评论送书】5月书讯:流畅的Python CSDN日报20170531 ——《这个架构能实现吗?》 CSDN 日报 | 4.19-5.19 上榜作者排行出炉 ...vectorc++stringinsert测试数据结构 ht
    
    

    c++中vector的用法详解

    标签: vectorc++stringinsert测试数据结构          http://blog.csdn.net/hancunai0017/article/details/7032383
    197419人阅读 评论(15)收藏举报
    本文章已收录于:
    分类:
          vector(向量): C++中的一种数据结构,确切的说是一个类.它相当于一个动态的数组,当程序员无法知道自己需要的数组的规模多大时,用其来解决问题可以达到最大节约空间的目的.

         用法:

              1.文件包含:     

               首先在程序开头处加上#include<vector>以包含所需要的类文件vector

              还有一定要加上using namespace std;

     

              2.变量声明:

                   2.1 例:声明一个int向量以替代一维的数组:vector <int> a;(等于声明了一个int数组a[],大小没有指定,可以动态的向里面添加删除)。

                   2.2 例:用vector代替二维数组.其实只要声明一个一维数组向量即可,而一个数组的名字其实代表的是它的首地址,所以只要声明一个地址的向量即可,即:vector <int *> a.同理想用向量代替三维数组也是一样,vector <int**>a;再往上面依此类推.

     

              3.具体的用法以及函数调用:

              3.1 如何得到向量中的元素?其用法和数组一样:

              例如:

              vector <int *> a

              int b = 5;

              a.push_back(b);//该函数下面有详解

              cout<<a[0];       //输出结果为5

    1.push_back   在数组的最后添加一个数据
    2.pop_back    去掉数组的最后一个数据 
    3.at                得到编号位置的数据
    4.begin           得到数组头的指针
    5.end             得到数组的最后一个单元+1的指针
    6.front        得到数组头的引用
    7.back            得到数组的最后一个单元的引用
    8.max_size     得到vector最大可以是多大
    9.capacity       当前vector分配的大小
    10.size           当前使用数据的大小
    11.resize         改变当前使用数据的大小,如果它比当前使用的大,者填充默认值
    12.reserve      改变当前vecotr所分配空间的大小
    13.erase         删除指针指向的数据项
    14.clear          清空当前的vector
    15.rbegin        将vector反转后的开始指针返回(其实就是原来的end-1)
    16.rend          将vector反转构的结束指针返回(其实就是原来的begin-1)
    17.empty        判断vector是否为空
    18.swap         与另一个vector交换数据

     

             3.2  详细的函数实现功能:其中vector<int> c.

                                 c.clear()         移除容器中所有数据。

                                 c.empty()         判断容器是否为空。

                                 c.erase(pos)        删除pos位置的数据

                                 c.erase(beg,end) 删除[beg,end)区间的数据

                                 c.front()         传回第一个数据。

                                 c.insert(pos,elem)  在pos位置插入一个elem拷贝

                                 c.pop_back()     删除最后一个数据。

                                 c.push_back(elem) 在尾部加入一个数据。

                                 c.resize(num)     重新设置该容器的大小

                                 c.size()         回容器中实际数据的个数。

                                 c.begin()           返回指向容器第一个元素的迭代器

                                 c.end()             返回指向容器最后一个元素的迭代器


                   4.内存管理与效率

          1》使用reserve()函数提前设定容量大小,避免多次容量扩充操作导致效率低下。

            关于STL容器,最令人称赞的特性之一就是是只要不超过它们的最大大小,它们就可以自动增长到足以容纳你放进去的数据。(要知道这个最大值,只要调用名叫max_size的成员函数。)对于vector和string,如果需要更多空间,就以类似realloc的思想来增长大小。vector容器支持随机访问,因此为了提高效率,它内部使用动态数组的方式实现的。在通过 reserve() 来申请特定大小的时候总是按指数边界来增大其内部缓冲区。当进行insert或push_back等增加元素的操作时,如果此时动态数组的内存不够用,就要动态的重新分配当前大小的1.5~2倍的新内存区,再把原数组的内容复制过去。所以,在一般情况下,其访问速度同一般数组,只有在重新分配发生时,其性能才会下降。正如上面的代码告诉你的那样。而进行pop_back操作时,capacity并不会因为vector容器里的元素减少而有所下降,还会维持操作之前的大小。对于vector容器来说,如果有大量的数据需要进行push_back,应当使用reserve()函数提前设定其容量大小,否则会出现许多次容量扩充操作,导致效率低下。

          reserve成员函数允许你最小化必须进行的重新分配的次数,因而可以避免真分配的开销和迭代器/指针/引用失效。但在我解释reserve为什么可以那么做之前,让我简要介绍有时候令人困惑的四个相关成员函数。在标准容器中,只有vector和string提供了所有这些函数。

    (1) size()告诉你容器中有多少元素。它没有告诉你容器为它容纳的元素分配了多少内存。
    (2) capacity()告诉你容器在它已经分配的内存中可以容纳多少元素。那是容器在那块内存中总共可以容纳多少元素,而不是还可以容纳多少元素。如果你想知道一个vector或string中有多少没有被占用的内存,你必须从capacity()中减去size()。如果size和capacity返回同样的值,容器中就没有剩余空间了,而下一次插入(通过insert或push_back等)会引发上面的重新分配步骤。
    (3) resize(Container::size_type n)强制把容器改为容纳n个元素。调用resize之后,size将会返回n。如果n小于当前大小,容器尾部的元素会被销毁。如果n大于当前大小,新默认构造的元素会添加到容器尾部。如果n大于当前容量,在元素加入之前会发生重新分配。
    (4) reserve(Container::size_type n)强制容器把它的容量改为至少n,提供的n不小于当前大小。这一般强迫进行一次重新分配,因为容量需要增加。(如果n小于当前容量,vector忽略它,这个调用什么都不做,string可能把它的容量减少为size()和n中大的数,但string的大小没有改变。在我的经验中,使用reserve来从一个string中修整多余容量一般不如使用“交换技巧”,那是条款17的主题。)

         这个简介表示了只要有元素需要插入而且容器的容量不足时就会发生重新分配(包括它们维护的原始内存分配和回收,对象的拷贝和析构和迭代器、指针和引用的失效)。所以,避免重新分配的关键是使用reserve尽快把容器的容量设置为足够大,最好在容器被构造之后立刻进行。

    例如,假定你想建立一个容纳1-1000值的vector<int>。没有使用reserve,你可以像这样来做:

    vector<int> v;
    for (int i = 1; i <= 1000; ++i) v.push_back(i);
    在大多数STL实现中,这段代码在循环过程中将会导致2到10次重新分配。(10这个数没什么奇怪的。记住vector在重新分配发生时一般把容量翻倍,而1000约等于210。)

    把代码改为使用reserve,我们得到这个:

    vector<int> v;
    v.reserve(1000);
    for (int i = 1; i <= 1000; ++i) v.push_back(i);
    这在循环中不会发生重新分配。

    在大小和容量之间的关系让我们可以预言什么时候插入将引起vector或string执行重新分配,而且,可以预言什么时候插入会使指向容器中的迭代器、指针和引用失效。例如,给出这段代码,

    string s;
    ...
    if (s.size() < s.capacity()) {
    s.push_back('x');
    }
    push_back的调用不会使指向这个string中的迭代器、指针或引用失效,因为string的容量保证大于它的大小。如果不是执行push_back,代码在string的任意位置进行一个insert,我们仍然可以保证在插入期间没有发生重新分配,但是,与伴随string插入时迭代器失效的一般规则一致,所有从插入位置到string结尾的迭代器/指针/引用将失效。

    回到本条款的主旨,通常有两情况使用reserve来避免不必要的重新分配。第一个可用的情况是当你确切或者大约知道有多少元素将最后出现在容器中。那样的话,就像上面的vector代码,你只是提前reserve适当数量的空间。第二种情况是保留你可能需要的最大的空间,然后,一旦你添加完全部数据,修整掉任何多余的容量。

           2》使用“交换技巧”来修整vector过剩空间/内存

          有一种方法来把它从曾经最大的容量减少到它现在需要的容量。这样减少容量的方法常常被称为“收缩到合适(shrink to fit)”。该方法只需一条语句:vector<int>(ivec).swap(ivec);
    表达式vector<int>(ivec)建立一个临时vector,它是ivec的一份拷贝:vector的拷贝构造函数做了这个工作。但是,vector的拷贝构造函数只分配拷贝的元素需要的内存,所以这个临时vector没有多余的容量。然后我们让临时vector和ivec交换数据,这时我们完成了,ivec只有临时变量的修整过的容量,而这个临时变量则持有了曾经在ivec中的没用到的过剩容量。在这里(这个语句结尾),临时vector被销毁,因此释放了以前ivec使用的内存,收缩到合适。

         3》用swap方法强行释放STL Vector所占内存

    template < class T> void ClearVector( vector<T>& v )
    {
        vector<T>vtTemp;
        vtTemp.swap( v );
    }

        vector<int> v ;
        nums.push_back(1);
        nums.push_back(3);
        nums.push_back(2);
        nums.push_back(4);
        vector<int>().swap(v);

    /* 或者v.swap(vector<int>()); */

    /*或者{ std::vector<int> tmp = v;   v.swap(tmp);   }; //加大括号{ }是让tmp退出{ }时自动析构*/

     

    5.Vector 内存管理成员函数的行为测试

           C++ STL的vector使用非常广泛,但是对其内存的管理模型一直有多种猜测,下面用实例代码测试来了解其内存管理方式,测试代码如下:

    #include <iostream>
    #include <vector>
    using namespace std;

    int main()
    {
    vector<int> iVec;
    cout << "容器 大小为: " << iVec.size() << endl;
    cout << "容器 容量为: " << iVec.capacity() << endl; //1个元素, 容器容量为1

    iVec.push_back(1);
    cout << "容器 大小为: " << iVec.size() << endl;
    cout << "容器 容量为: " << iVec.capacity() << endl; //2个元素, 容器容量为2

    iVec.push_back(2);
    cout << "容器 大小为: " << iVec.size() << endl;
    cout << "容器 容量为: " << iVec.capacity() << endl; //3个元素, 容器容量为4

    iVec.push_back(3);
    cout << "容器 大小为: " << iVec.size() << endl;
    cout << "容器 容量为: " << iVec.capacity() << endl; //4个元素, 容器容量为4

    iVec.push_back(4);
    iVec.push_back(5);
    cout << "容器 大小为: " << iVec.size() << endl;
    cout << "容器 容量为: " << iVec.capacity() << endl; //5个元素, 容器容量为8

    iVec.push_back(6);
    cout << "容器 大小为: " << iVec.size() << endl;
    cout << "容器 容量为: " << iVec.capacity() << endl; //6个元素, 容器容量为8

    iVec.push_back(7);
    cout << "容器 大小为: " << iVec.size() << endl;
    cout << "容器 容量为: " << iVec.capacity() << endl; //7个元素, 容器容量为8

    iVec.push_back(8);
    cout << "容器 大小为: " << iVec.size() << endl;
    cout << "容器 容量为: " << iVec.capacity() << endl; //8个元素, 容器容量为8

    iVec.push_back(9);
    cout << "容器 大小为: " << iVec.size() << endl;
    cout << "容器 容量为: " << iVec.capacity() << endl; //9个元素, 容器容量为16
    /* vs2005/8 容量增长不是翻倍的,如
        9个元素   容量9
        10个元素 容量13 */

    /* 测试effective stl中的特殊的交换 swap() */
    cout << "当前vector 的大小为: " << iVec.size() << endl;
    cout << "当前vector 的容量为: " << iVec.capacity() << endl;
    vector<int>(iVec).swap(iVec);

    cout << "临时的vector<int>对象 的大小为: " << (vector<int>(iVec)).size() << endl;
    cout << "临时的vector<int>对象 的容量为: " << (vector<int>(iVec)).capacity() << endl;
    cout << "交换后,当前vector 的大小为: " << iVec.size() << endl;
    cout << "交换后,当前vector 的容量为: " << iVec.capacity() << endl;

    return 0;
    }

    6.vector的其他成员函数

            c.assign(beg,end):将[beg; end)区间中的数据赋值给c。
            c.assign(n,elem):将n个elem的拷贝赋值给c。
            c.at(idx):传回索引idx所指的数据,如果idx越界,抛出out_of_range。
            c.back():传回最后一个数据,不检查这个数据是否存在。
            c.front():传回地一个数据。
            get_allocator:使用构造函数返回一个拷贝。
            c.rbegin():传回一个逆向队列的第一个数据。
            c.rend():传回一个逆向队列的最后一个数据的下一个位置。
            c.~ vector <Elem>():销毁所有数据,释放内存。   

    7.备注:在用vector的过程中的一些问题,特此列出讨论:

                   1)

                        vector <int > a;

                        int  b = 5;

                        a.push_back(b);

                        此时若对b另外赋值时不会影响a[0]的值

                    2)

                        vector <int*> a;
                         int *b;
                         b= new int[4];
                         b[0]=0;
                         b[1]=1;
                         b[2]=2;
                         a.push_back(b);
                         delete b;          //释放b的地址空间
                         for(int i=0 ; i <3 ; i++)
                         {
                               cout<<a[0][i]<<endl;
                         }

                         此时输出的值并不是一开始b数组初始化的值,而是一些无法预计的值.

                        分析:根据1) 2)的结果,可以想到,在1)中,  往a向量中压入的是b的值,即a[0]=b,此时a[0]和b是存储在两个不同的地址中的.因此改变b的值不会影响a[0];而在2)中,因为是把一个地址(指针)压入向量a,即a[0]=b,因此释放了b的地址也就释放了a[0]的地址,因此a[0]数组中存放的数值也就不得而知了.



    C++中vector<int>a,b(n,0)什么意思 

    推荐于2016-11-12 03:24:37 最佳答案 https://zhidao.baidu.com/question/502212190.html
    Vector 容器:
    vector类称作向量类,它实现了动态的数组,用于元素数量变化的对象数组。
    构造函数:
    vector():创建一个空的vector。
    vector(itn nSize):创建一个vector,元素个数为nSize。
    
    vector(int nSize, const T& t):创建一个vector,元素个数为nSize,且值均为t。
    
    vector(const vector&):拷贝构造函数。
    
    vector<int>a,b(n,0)的意思就是 创建了一个 int 类型的空的vector容器a,和一个 int 类型n个元素,且值均为0的vecotr容器b。

    展开全文
  • vector C++ 详细用法

    千次阅读 2013-07-18 00:41:54
    vectorc++iterator数据结构exceptionalgorithm  vector是C++标准模板库中的部分内容,它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库。vector之所以被认为是一个容器,是因为它能够像容器一样...
  • STL vector用法介绍

    2016-07-22 10:48:23
    STL 之 vector 介绍 这篇文章的目的是为了介绍std::vector,如何恰当地使用它们的成员函数等操作。本文中还讨论了条件函数和函数指针在迭代算法中使用,如在remove_if()和for_each()中的使用。...vectorC+
  • 最近在复习三月份的ccf,搜寻到了一些比较好的博客和笔记,在此放置一下传送门vectorC++ vector 容器浅析setC++ STL set容器常用用法mapC++中的STL中map用法详解stringC++ string的用法和例子在此感谢做出这些笔记的...
  • http://blog.csdn.net/hancunai0017/article/details/7032383 c++中vector的用法详解 分类: c语言2011-12-01 ...vectorc++stringinsert测试数据结构  vector(向量): C++中的一种数据结构,确
  • C++ Vector用法深入剖析

    2015-09-08 14:19:22
    C++ Vector应用方式是比较特殊的,我们将会在这篇文章中针对于它的应用方式进行一个详细的介绍,希望大家能充分掌握这一应用技巧。 ...C++编程语言中有一种叫做Vector的应用方法,它的作用在实际编程中是非常...C+
  • 严重性 代码 说明 项目 文件 行 禁止显示状态 错误(活动) E1087 没有与参数列表和对象匹配的... i++) { if (books[i].getBookName.find(s) != string::npos) { vec.push_back(i);//163行 } } } ```
  • C++中vector用法

    2010-12-29 14:53:00
    vector有两种用法:1。vector vector(elem_size)该种方法的括号里的内容不仅仅可以是元素的个数。vector不能像C中的数组一样初始化int array[6] = {1, 2, 3, 4, 5, 6};但是可以把一个已有的数组给vector初始化:...
  • vector是一个容器,它能够存放各种类型的对象,简单地说,vector是一个能够存放任意类型的动态数组,可以动态改变大小。 一.常用操作 头文件 #include<vector> c.clear() //移除容器中所有数据。 c....
  • 15.7 操作符 ++和-- 676 15.8 操作符new和delete 680 15.9 用户定义的转换 688 15.10 选择一个转换 ※ 697 15.11 重载解析和成员函数 ※ 708 15.12 重载解析和操作符 ※ 713 第16章 类模板 722 16.1 类模板定义 722 ...
  • <code class="language-cpp">#include <iostream> #include<string> #include<vector> using namespace std;...typename Object, typename Comparator>...也没有搜到类似的用法c;求指点啊</p>
  • 原帖地址:http://hi.baidu.com/yanfei_1/blog/item/a0a538331f5256f91a4cffba.htmlC++的标准模板库(Standard Template Library,简称STL)是一个容器和算法的类库。容器往往包含同一类型的数据。STL中比较常用的...
  • 原帖地址:http://hi.baidu.com/yanfei_1/blog/item/a0a538331f5256f91a4cffba.htmlC++的标准模板库(Standard Template Library,简称STL)是一个容器和算法的类库。容器往往包含同一类型的数据。STL中比较常用的...
  • [转载]vector容器

    2018-07-11 23:34:01
    https://www.cnblogs.com/YJthua-china/p/6550960.htmlC++序列容器之 vector常见用法总结一、关于vector 本文默认读者具有一定的c++基础,故大致叙述,但保证代码正确。 vector是一个动态的序列容器,相当于一个...
  • C ++提供了一个内置的数组类型,它基于C ++C继承的语言模型。由于Vector集合类的统一性更加灵活和方便,所以在新代码中使用数组的原因很少。(在现有应用程序中尽管你一定会遇到矩阵) 在C ++中,数组是具有两个...
  • java集合框架的基本接口/类层次结构 java.util.Collection [I] +--java.util.List [I] +--java.util.ArrayList [C] +--java.util.LinkedList ... +--java.util.Vector [C] +--java.util.Stack [C] +--java.util.
  • 1.关于setC++ STL 之所以得到广泛的赞誉,也被很多人使用,不只是提供了像vector, string, list等方便的容器,更重要的是STL封装了许多复杂的数据结构算法和大量常用数据结构操作。vector封装数组,list封装了链表,...

空空如也

空空如也

1 2 3 4 5
收藏数 98
精华内容 39
关键字:

vectorc++用法

c++ 订阅