c++ STL之vector基本使用


本質

內部是一個數組,增加和刪除的時候涉及到大量元素移動、復制,所以耗時
數組大小可變,當插入操作超過默認大小,會重新分布內存
內部維護的是拷貝的數據,對原數據進行操作,不會更改vector內部數據

頭文件

#include <vector>
需要使用std 命名空間

增加

定義 vector<int> test{1, 2, 3, 4};
1.在尾部直接插入元素
test.push_back(1);
2.使用迭代器,第一個參數傳入一個指向當前vector的迭代器,第二個參數傳入值
test.insert(test.begin(), 1); //在頭部插入
有多個重載函數:
   填充指定個數的元素
   test.insert(test.begin(), 10, 1); //第一個參數是迭代器位置,第二個參數是個數,第三個參數是值
   插入迭代器范圍的數據
   test.insert(test.begin(), test.begin(), test.end());
   第一個參數是插入迭代器位置,第二個參數和第三個參數是范圍,左閉右開
3.值得注意的是,由於vector是可變的,像vector插入后,可能使所有指向vector的指針、迭代器失效
當添加到一定大小,vector就會重新分配空間,將舊的空間元素拷貝到新空間中,釋放舊空間
4.函數的參數的迭代器由於3的原因可能失效,但是返回值一定不會失效
看源碼可知返回值使用begin() + __offset,而不是傳入的參數迭代器,就是因為可能內存重新分配

如果你在做一個循環插入或者賦值的首推薦

#include <iostream>
#include <vector>
using namespace std;
int main() {
    vector<int> test{1, 2, 3, 4};
    for(vector<int>::iterator test_iterator = test.begin(); test_iterator != test.end(); test_iterator++) {
        if(*test_iterator == 3) {
            test_iterator = test.insert(test_iterator, 4);
            if( test_iterator + 1 == test.end()) {
                break;                
            }
            test_iterator++;
        }
    }

    return 0;
}

當滿足條件插入后,防止迭代器失效,使用insert的返回值進行重新賦值,之后的 test_iterator++;是因為test_iterator當前指向4,如果不連着加兩次會陷入死循環,下一個再加就到了4

刪除

1.刪除尾部元素
test.pop_back(); 
2.使用迭代器
test.erase(test.begin());  //參數為迭代器位置,返回值為迭代器位置
多個重載函數
test.erase(test.begin(), test.end() - 1);   //刪除迭代器的范圍元素,左閉右開
3.迭代器循環刪除,這個是比較有爭議的
對於erase的返回值:
An iterator pointing to the next element (or end()).
指向下一個元素的迭代器

關於erase有詳述
本人這里認為返回的迭代器就是指向的你刪除元素之后的元素,注意的是迭代器本身沒有改變,只不過是元素遷移了

循環刪除推薦

#include <iostream>
#include <vector>
using namespace std;
int main() {
    vector<int> test{1, 2, 3, 4};

    
    for(vector<int>::iterator test_iterator = test.begin(); test_iterator != test.end();) {
        if(*test_iterator == 3) {
            test_iterator = test.erase(test_iterator);
        }
        else {
            test_iterator++;
        }
    }

    return 0;
}

4.網上好多提到remove函數
千篇一律都是remove和erase搭配,我erase明明就可以實現,要remove干嘛呢?
為了刪除范圍內所有的指定元素,erase函數只能刪除單個的,要不就是一個范圍,沒有remove這種條件的刪除

 remove不是成員函數,不能真正的刪除
 這里先說__remove_if,remove本質也是__remove_if
 __remove_if是有條件的刪除,第一個參數和第二個參數代表范圍,第三個參數構建一個value值的對象
 然后在__remove_if內部對給定值比較,做了一個for循環賦值,把不等於給定值的都移動到前面
 這樣到最后,把等於給定值的第一個迭代器返回
 這就是remove的核心,的確不能直接刪除元素,但是remove對整個迭代器區間的元素進行了重新賦值分配,划分了兩撥,前面是不含有給定值的,后面是含有給定值的來個圖片

之后就是配合erase的迭代器區間刪除函數就可以了
remove頭文件是#include <algorithm>

例子

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


int main() {
    vector<int> test{1,3,3,3,4,3};

    for(vector<int>::iterator test_iterator = test.begin(); test_iterator != test.end(); test_iterator++) {
        std::cout << *test_iterator << std::endl;
    }

    test.erase(remove(test.begin(), test.end(), 3), test.end());

    for(vector<int>::iterator test_iterator = test.begin(); test_iterator != test.end(); test_iterator++) {
        std::cout << *test_iterator << std::endl;
    }
    //刪除前1,3,3,3,4,3
    //刪除后1,4

    return 0;
}

訪問和改動

1.使用迭代器進行修改
STL中迭代器有兩種,一種是const_iterator,一種是iterator,區別就是const_iterator只能讀取和調用const相關的函數,iterator都可以
本質就是const和非const的區別
我們可以使用迭代器-> 調用迭代器指向的內存變量的函數,迭代器-> 和 內存變量. 的操作是一樣的
也可以使用 *迭代器. 的操作,這樣就是拿到迭代器指向的變量然后操作
2.c.back(); //返回c中尾元素的引用,如果c為空,函數未定義
3.c.front(); //返回c中首元素的引用,如果c為空,函數未定義
4.c[n]; //返回c中下標為n的元素引用,如果n>=c.size(),行為未定義
5.c.at[n]; //返回下標為n的元素引用,如果下標越界,拋出異常

這些訪問元素的成員函數返滬的都是引用,容器是const,返回的是const引用,不是const,返回普通引用。內部根據const重載了訪問函數

添加刪除都要考慮迭代器失效問題

使用insert和erase返回值更新迭代器


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM