c++ vector詳解


1.前言

本文mark了vector的一些接口,介紹了vector中的對內存和對象的管理詳解請見cppreference-vector
1.vector內部管理着一塊內存,壓入對象的時候,會使用這塊內部的內存使用placement new去進行對象的生成,而釋放對象的時候,顯式的去調用析構函數去釋放對象
2.size代表vector中的實際含有元素數量,而capacity表示容量
3.resize()調整size的時候會生成或釋放元素,釋放的本質只是調用了析構,但是那塊內存塊還在vector中
4.reserve()調整capacity的時候只會增大但是不會減小
5.push_back()同時支持copy構造&和移動語義構造&&,配合std::move或者std::forward效果更佳
6.earse()用來刪除元素,參數是迭代器, 范圍刪除的時候是前閉后開【 )
7.emplace()相當於insert(),但是其通過參數包和模板偏特化減少了一次拷貝構造的過程

2.正文

2.1 vector基本布局

一個簡單的vector,我們可以理解成如下形式,主要是舉了reserve()和resize()這兩個例子,來舉例vector是如何分配內存,創建初始化對象的,以及析構對象的;
vector內部管理着一塊內存,當需要push_back對象得時候,會使用這塊內部的內存使用placement new去進行對象的生成,而釋放對象的時候,顯示的去調用析構函數去釋放對象(這只是一種理解,實際實現不一定如此,但是原理上大同小異)

template<class T>
class vector{
    public:
        unsigned char *buffer;
        int size_;
        int capacity_;
        T value_type;
        
        //分配內存
        void reserve(int capacity){
           if(capacity > capacity_){//創建一塊新內存放過去
                unsigned char * temp = malloc(sizeof(value_type) * capacity); 
                memcpy(temp, buffer, capacity_);
                capacity_ = capacity;
                free(buffer);
                buffer = temp;
           }
        }
        
         //調整元素
        void resize(int size){
            int duration = sizeof(value_type);
            if(size > size_){
                for(int i = size_ ; i < size ; ++i){
                    T *obj = new(buffer[i*duration])T();//使用buffer[i * duration]內存塊去創建對象
                }
            }
            else{
                for(int i = size_ -  1; i >= size ; --i){
                    T *obj = (T*) buffer[ i* duration];
                    obj->~T();//調用析構

                }
            }
        }
};

2.2 constructor

  • 基本構造函數
    有四種如下的方式,其中特別注意使用iterator的方式進行copy construct的時候,也可以直接傳遞數組地址過去,會自動轉換
// constructors used in the same order as described above:
  std::vector<int> first;                                // empty vector
  std::vector<int> second (4,100);                       // four ints with value 100
  std::vector<int> third (second.begin(),second.end());  // iterating through second
  std::vector<int> fourth (third);                       // a copy of third

// the iterator constructor can also be used to construct from arrays:
  int myints[] = {16,2,77,29};
  std::vector<int> fifth (myints, myints + sizeof(myints) / sizeof(int) );
    
  • 列表初始化
    可以使用c++11的列表初始化進行快速初始化
vector<int> a{{1}, {2}, {3}};    //加不加括號都一樣
vector<int> a={{1}, {2}, {3}};

2.3 size()和capacity()

size是指當前vector中含有的元素數量,capacity是指vector中擁有的空間

  • void resize (size_type n);

調整vector的size, 如果size比當前擁有的大,會創建默認對象進行push_back,如果size比當前的小,會縮小size,但是不縮小capacity,創建和釋放會調用構造函數與析構函數

vector<int> v;
v.resize(5);    //調整元素個數
  • void reserve (size_type n);

調整vector的capacity,如果capacity比當前的小,不縮小,反之,則增加capacity

vector<int> v;
v.reserve(5);    //調整容量大下
  • value_type* data() noexcept;
    返回內存塊的指針首地址
vector<int> v(10);
int *p = v.data(); //獲取內存塊首地址

2.4 element access

  • reference at (size_type n);
    返回對應的位置元素的引用,和[]作用相同,但是會做檢查
vector<int> v(10);
int number = v.at(0); //獲取

2.5 Modifiers

  • [std::vector::push_back]
    插入,參數支持引用和右值
void push_back (const value_type& val);
void push_back (value_type&& val);
  // erase the 6th element
  myvector.erase (myvector.begin()+5);

  // erase the first 3 elements:
  myvector.erase (myvector.begin(),myvector.begin()+3)
int myints[] = {1776,7,4};
third.assign (myints,myints+3);   // assigning from array.

插入,和insert一樣,但能可以減少一次copy構造, 因為參數是一個變參包,這個變參數包通過模板偏特化匹配解包,傳遞給對應類的構造函數直接構造對象, 我們可以這么理解參數包的運行過程:emplace將參數包傳到temp中,會首先根據當前的參數找到偏特化的實現的模板 class temp, 然后調用其構造函數,此處用到了參數包+模板偏特化實現參數匹配。

class temp{
public:
       temp(int a, int b){
            cout<<"a:"<<a<<"b:"<<b<<endl;  // 1 2
            cout<<"construct\n";
        }
}

template <class type>
class vector{
    public:
    template<class ...args>
    emplace(vector<type>::Iterator iter, args ...a){
        .....
        
        //將這個參數包傳給temp(int a, int b)
        temp(a...);
        .....
    }
}

vector<temp> v;
v.emplace(v.begin(), 1,2);


免責聲明!

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



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