c++vector基础知识

vector 是STL中应用最为广泛的一类容器,这里对其重要的特性做一个概括和总结。

  • vector的初始化
    • vector的初始化,见如下代码。

      vector<int> v2;       // vector with 0 element
      vector<int> v3(20);   // vector with 20 elements whose value is 0
      vector<int> v4(20, 5);// vector with 20 elements whose value is 5
      vector<int> v5{ 20 }; // vector with 1 element whose value is 20
      vector<int> v6(v4);   // copy construct function
      vector<int> v7(v4.begin(), v4.end());//construct function
      vector<int> v8({ 1,2,3,4,5 });// construct a vector with initialize list
      vector<int> v9{ 1,2,3,4,5 };// construct a vector with initialize list
      vector<int> v10 = {1,2,3,4,5};// assignment construct function

  • vector的容量和大小
    1. vector在内存中按照连续方式进行存储,因此初始化vector时会有一个初始的容量(capacity),容量(capacity)类似于一个电梯的最大容纳重量。

    2. 向vector中添加数据的时候,如果当前元素个数(size)小于容量(capacity),那么就会继续在相应位置插入元素。如果当前元素个数和容量相等,则会对vector的容量进行扩展,一般容量按照当前数据量的2倍方式增长。

    3. reserve可以对vector的容量进行设置,如果即将设置的容量小于当前容量,则vector的容量不会缩小。而如果设置的值大于当前容量,那么会分配设置的容量。如下代码:
    vector<int> v2;
    v2.reserve(20);
    cout << v2.capacity() << endl;  // capacity is set to be 20
    v2.reserve(10);
    cout << v2.capacity() << endl;  // capacity is still 20
    1. resize函数对vector当前元素个数进行大小设置,resize(n),表示将元素个数设置为n个,如果n小于当前size,则会将超过n的元素截断,只留下n个元素。如果n大于当前size,则将需要添加的元素默认设置为0,如果resize(n,m),则表示将新增元素初始化为m,具体用法如下:
    vector<int> values{1,2,3};  // 1 2 3 : size is 3
    values.resize(5);           // 1 2 3 0 0 : size is 5
    values.resize(7,99);        // 1 2 3 0 0 99 99 : size is 7
    values.resize(6);           // 1 2 3 0 0 99 : size is 6

    说明:resize(0)并不能将vector中的内存释放,vector的容量不会有任何影响,如果想将vector的capacity设置为0,则有如下办法:

    • 方法一:clear和shrink_to_fit
    vector<int> v2;
    v2.reserve(20);       // capacity is set to be 20
    v2.clear();                     
    v2.shrink_to_fit(); //clear and shrink_to_fit to set capacity to 0
    • 方法二:resize和shrink_to_fit
    vector<int> v2;
    v2.reserve(20);     // capacity is set to be 20
    v2.resize(0);       // resize to be 0 element               
    v2.shrink_to_fit();//resize and shrink_to_fit to set capacity to 0
    • 方法三: swap方法
    vector<int> v2;
    v2.reserve(20);    // capacity is set to be 20
    vector<int> v3;    // capacity is 0
    swap(v2,v3);       // v2's capacity is 0
    1. vector的元素个数等于当前容量时,vector中再次增加元素时,vector的容量就会增大,一般按照当前已有元素的50%进行扩展,当容量太大而不需要时,可以采用shrink_to_fit()来除去多余的容量以减少内存占用量。

  • vector访问元素
    • vector可以通过方括号使用索引进行元素访问,也可以通过at(index)方式访问,但是at的访问效率比方括号的访问效率低,这是因为at函数会检查索引越界问题,而方括号不会检查索引是否越界。

    • 成员函数front()和back()函数可以返回vector中第一个和最后一个元素的引用,因为返回的是引用,因而可以进行赋值操作。例如:
    vector<int> vec{1,2,3,4};
    vec.back() = 100;    // set last element to 100
    vec.front() = 10;    // set first element to 10
    • 成员函数data()用于返回一个指向数组的指针,它在内部被用来存储元素。
    vector<int> values(10,100);
    auto pData = values.data();// pData is a pointer point to int*

  • vector添加元素
  • 注意:向容器中添加元素的唯一方式是使用它的成员函数。如果不调用成员函数,非成员函数既不能添加也不能删除元素。这意味着容器对象必须通过他所允许的函数去访问,迭代器是不行的。

    • 增加元素。可以通过使用容器对象的push_back()和emplace_back()函数在序列的末尾添加一个元素。注意:emplace_back比push_back更加有效率。这是因为emplace_back()的参数正是添加到容器中的对象构造函数所需要的参数。emplace_back用它的参数作为构造函数的参数,在容器中生成对象。
    vector<string> vec;
    // 生成一个临时string对象,再将临时对象放入vector末尾
    vec.push_back("hello world1");
    // 直接当做参数传递给末尾string的构造函数,没有产生临时对象这一步骤
    vec.emplace_back("hello world2");
    string str ("to be or not to be");
    // emplace_back()中可以直接传string的构造函数所需要的参数
    vec.emplace_back(str,0,18);
    1. 插入元素。通过成员函数emplace(),可以在vector序列中插入新的元素。对象会在容器中直接生成,而不是先单独生成对象,然后把它作为参数传入。emplace()的第一个参数是指定对象的插入位置,后面的参数是构造该对象需要的参数,根据vector中存储的对象类型不同,其传入的参数也会不同。

    2. 通过成员函数insert()可以在vector中插入一个或者多个元素,第一个参数总是一个指向插入点的const或者non-const迭代器。元素会被迅速插入到第一个参数所指向元素的前面,如果第一个参数是反向迭代器,元素会被插入到迭代器所指向元素的后面。代码示例如下。

    vector<string> v2;
    v2.emplace_back("second");              // second
    string str1 = "first";  
    v2.emplace(v2.begin(), str1);           // first second     
    string str2 = "third";
    v2.emplace(v2.begin() + 1,  str2,  0,  5);  // first third second
    v2.emplace(v2.begin()+1, 4, 'z');           
    1. 插入单个元素,insert第二个参数指定插入的值。insert插入单个元素时有两个重载的版本函数,两个函数第一个参数都是指定插入位置,第二个参数指定插入元素。第一个版本插入元素类型为const T&,第二个版本的类型是T&&——右值引用。右值引用对象是一个临时对象,因此插入过程中被移动插入而不是复制插入。注意:使用同样的参数情况下,调用insert()没有调用emplace()高效。下述调用insert的函数会生成一个临时对象作为传入的第二个参数,但是在emplace()调用中,构造函数用第二个参数直接在容器中生成了字符串对象。如下代码:
    vector<string> words {"one","three","eight"};
    
    // iter1 point to elment being inserted
    auto iter1 = words.insert (words.begin()+1,"two")// T&& version,one two three eight,
    
    words.emplace(words.begin()+1"two");// more effective than insert.
    string str = "nine";
    // iter2 point to elment being inserted
    // cosnt T& version,one two three eight nine
    auto iter2 = words.insert (words.end(),str);
    
    1. 插入元素序列。insert函数可以在某个特定位置前面插入一系列元素。这是emplace函数所不具有的功能当插入一系列元素时,insert返回第一个插入的元素的位置。
    string more[] = {"five","six","seven"};
    vector<string> words;
    words.insert (words.begin(),begin(more),end(more));
    words.insert (words.end(),{"some", "one", "like", "you"});
    words.insert (wrods.begin()+1,5,"forward");    // insert 5 "forward"

  • vector删除元素
    1. 使用clear函数将vector中的元素清空,但是capacity并不会释放。
    2. 使用pop_back()可以删除容器尾部元素。假若要删除vector中某个位置的元素,可以使用swap和最后一个元素交换,然后使用pop_back()删除最后一个元素。代码示例如下。
    vector<int> vec = {1,3,5,7,9};
    vec.swap(vec.begin()+1,vec.end()-1);
    vec.pop_back();     // remove 3
    1. 成员函数erase可以用来删除容器中一个或者多个元素,如果只需要删除一个元素,则提供一个迭代器位置即可,删除元素后返回删除元素的下一个位置的迭代器。如果需要删除一定范围内的元素,需要提供两个参数,即删除范围的开始和结束位置。

    2. remove()算法可以删除指定范围内匹配特定值的元素。但是remove()是一个全局函数,不能删除容器中的元素。remove先在vector中寻找要删除的元素,随后将该元素后的所有元素前移,以覆盖该元素,最后将要删除的元素值设置为默认值。需要注意的是,remove()函数不会改变vector的大小和容量,因此为了删除多余的位置,需要配合erase使用。示例代码如下:

    vector<string> vec = {"one", "none", "some", "all", "none", "most", "many"};
    auto iter = remove(words.begin(),words.end(),"none");
    words.erase(iter,words.end());//remove surplus elements

    猜你喜欢

    转载自blog.csdn.net/t46414704152abc/article/details/79242957