STL中的向量 - vector

作者:billy
版權聲明:著作權歸作者所有,商業轉載請聯繫作者獲得授權,非商業轉載請註明出處

簡介

向量(Vector)是一個封裝了動態大小數組的順序容器(Sequence Container)。跟任意其它類型容器一樣,它能夠存放各種類型的對象。可以簡單的認爲,向量是一個能夠存放任意類型的動態數組。當程序員無法知道自己需要的數組的規模多大時,用 vector 來解決問題可以達到最大節約空間的目的。

vector 的動態擴充機制

vector是一塊連續分配的內存,從數據安排的角度來講,和數組極其相似, 不同的地方就是:

  • 數組是靜態分配空間,一旦分配了空間的大小,就不可再改變了;
  • 而 Vector 是動態分配空間,隨着元素的不斷插入,它會按照自身的一套機制不斷擴充自身的容量;

vector的擴充機制:按照容器現在容量的一倍進行增長。 vector容器分配的是一塊連續的內存空間,每次容器的增長,並不是在原有連續的內存空間後再進行簡單的疊加, 而是重新申請一塊更大的新內存,並把現有容器中的元素逐個複製過去,然後銷燬舊的內存。 這時原有指向舊內存空間的迭代器已經失效,所以當操作容器時,迭代器要及時更新。

vector 中 size、capacity、max_size 的區別

  • size:當前vector容器真實佔用的大小,也就是當前擁有多少個容器;
  • capacity:表示在發生 realloc 前能允許的最大元素數,也可以理解爲預分配的內存空間。例如一個 vector<int> v 的 capacity 爲10,當插入第11個元素時,vector 會 realloc,vector 內部數據會複製到另外一個內存區域。這樣之前指向 vector 中的元素的指針、迭代器等等均會失效;
  • max_size:表示容器允許的最大元素數。通常這個數是一個很大的常整數,可以理解爲無窮大,這個數目與平臺和實現相關。因爲 max_size 很大,所以基本不會發生元素數超過 max_size 的情況;

size 和 capacity 兩個屬性分別對應兩個方法:resize() 和 reserve()

  • 使用 resize() 容器內的對象內存空間是真正存在的;
  • 使用 reserve() 僅僅只是修改了 capacity 的值,容器內的對象並沒有真實的內存空間(空間是"野"的)。此時切記不要使用 [] 操作符訪問容器內的對象,很可能出現數組越界的問題;

示例:

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

int main()
{
    vector<int> v;

    cout << "v.size() == " << v.size() << ", v.capacity() = " << v.capacity() << endl;

    v.reserve(10);

    cout << "v.size() == " << v.size() << ", v.capacity() = " << v.capacity() << endl;

    v.resize(10);
    v.push_back(0);

    cout << "v.size() == " << v.size() << ", v.capacity() = " << v.capacity() << endl;

    return 0;
}

運行結果:
v.size() == 0, v.capacity() = 0		//初始化完成,但是容器中沒有對象,也沒有預留內存空間
v.size() == 0, v.capacity() = 10	//reserve(10),預留10個對象的空間,但是容器內依然沒有對象,如果使用 [] 訪問會報越界錯誤
v.size() == 11, v.capacity() = 20	//resize(10),容器內的對象空間爲10個對象的空間,此時再添加一個對象,就要重新分配一次空間,容量爲原先的一倍。並把現有容器中的元素逐個複製過去,然後銷燬舊的內存

注意:capacity 和 reserve 只適用於 string 和 vector,STL容器中擁有 capacity 屬性的只有 string 和 vector

常用函數

  1. 構造
  • vector():創建一個空vector
  • vector(int nSize):創建一個vector,元素個數爲nSize
  • vector(int nSize, const t& t):創建一個vector,元素個數爲nSize,且值均爲t
  • vector(const vector&):複製構造函數
  • vector(begin, end):複製 [begin,end) 區間內另一個數組的元素到vector中
  1. 新增
  • void push_back(const T& x):向量尾部增加一個元素X
  • iterator insert(iterator it, const T& x):向量中迭代器指向元素前增加一個元素x
  • iterator insert(iterator it, int n, const T& x):向量中迭代器指向元素前增加n個相同的元素x
  • iterator insert(iterator it, const_iterator first, const_iterator last):向量中迭代器指向元素前插入另一個相同類型向量的 [first,last) 間的數據
  1. 刪除
  • iterator erase(iterator it):刪除向量中迭代器指向元素
  • iterator erase(iterator first, iterator last):刪除向量中 [first,last) 中元素
  • void pop_back():刪除向量中最後一個元素
  • void clear():清空向量中所有元素
  1. 遍歷
  • reference at(int pos):返回pos位置元素的引用
  • reference front():返回首元素的引用
  • reference back():返回尾元素的引用
  • iterator begin():返回向量頭指針,指向第一個元素
  • iterator end():返回向量尾指針,指向向量最後一個元素的下一個位置
  • reverse_iterator rbegin():反向迭代器,指向最後一個元素
  • reverse_iterator rend():反向迭代器,指向第一個元素之前的位置
  1. 大小
  • int size() const:返回向量中元素的個數
  • int capacity() const:返回當前向量所能容納的最大元素值
  • int max_size() const:返回最大可允許的vector元素數量值
  1. 其他
  • bool empty() const:判斷向量是否爲空,若爲空,則向量中無元素
  • void swap(vector&):交換兩個同類型向量的數據
  • void assign(int n, const T& x):設置向量中第n個元素的值爲x
  • void assign(const_iterator first, const_iterator last):向量中 [first,last) 中元素設置成當前向量元素

綜合運用示例

在這裏插入圖片描述

mymatrix.h

#ifndef MYMATRIX_H
#define MYMATRIX_H

#include <iostream>
#include <vector>
#include <math.h>
using namespace std;

template <class T>
class MyMatrix1f	// 列向量類
{
public:
    MyMatrix1f()	// 無參構造函數
    {
        matrix.reserve(3);
    }

    MyMatrix1f(T x, T y)	// 有參構造函數
    {
        matrix.reserve(3);
        matrix.push_back(x);
        matrix.push_back(y);
        matrix.push_back(1);
    }

    MyMatrix1f(const MyMatrix1f& vec)	// 拷貝構造函數
    {
        matrix.reserve(vec.matrix.size());

        for (auto &temp : vec.matrix)
        {
            matrix.push_back(temp);
        }
    }

    T operator()(size_t index)	// 重載運算符()
    {
        if (index >= matrix.size())
        {
            cout << "Out of range !" << endl;
            return 0;
        }

        return matrix.at(index);
    }

    void push(T value)	// 列向量添加元素
    {
        matrix.push_back(value);
    }

    void print()	// 打印列向量所有元素
    {
        for (auto &vec : matrix)
        {
            cout << vec << "\t";
        }
        cout << endl;
    }

private:
    vector<T> matrix;
};


template <class T>
class MyMatrix3f: public vector<vector<T>>	// 3x3變換矩陣類
{
public:
    MyMatrix3f(T h, T k, T a): vector<vector<T>>(0)	//有參構造函數
    {
        vector<T> v1, v2, v3;
        v1.reserve(3);
        v2.reserve(3);
        v3.reserve(3);

        v1.push_back(static_cast<T>( cos(a) ));
        v1.push_back(static_cast<T>( sin(a) * (-1) ));
        v1.push_back(h);

        v2.push_back(static_cast<T>( sin(a) ));
        v2.push_back(static_cast<T>( cos(a) ));
        v2.push_back(k);

        v3.push_back(0);
        v3.push_back(0);
        v3.push_back(1);

        this->reserve(3);
        this->push_back(v1);
        this->push_back(v2);
        this->push_back(v3);
    }

    T operator()(size_t x, size_t y)	// 重載運算符()
    {
        if (x >= this->size())
        {
            cout << "Out of range !" << endl;
            return 0;
        }

        vector<T> vec = this->at(x);
        if (y >= vec.size())
        {
            cout << "Out of range !" << endl;
            return 0;
        }

        return vec.at(y);
    }

    MyMatrix1f<T> operator*(MyMatrix1f<T>& matrix)	// 重載運算符*
    {
        MyMatrix1f<T> ret;
        for (auto &vec : *this)
        {
            T value = 0;
            size_t i = 0;
            for(auto &temp : vec)	// 矩陣乘法運算 - 矩陣的每一行乘以列向量的和成爲一個新的列向量
            {
                value += temp * matrix(i);
                i++;
            }
            ret.push(value);
        }
        return ret;
    }

    void print()	// 打印3x3變換矩陣所有元素
    {
        for (auto &vector : *this)
        {
            for (auto &vec : vector)
            {
                cout << vec << "\t\t";
            }
            cout << endl;
        }
    }
};

#endif // MYMATRIX_H
main.cpp

#include "mymatrix.h"

int main()
{
    MyMatrix1f<double> matrix1f(2, 4);
    matrix1f.print();
    cout << "matrix1f(1): " << matrix1f(1) << endl << endl;

    MyMatrix3f<double> matrix3f(10.0, 20.0, M_PI/3);
    matrix3f.print();
    cout << "matrix3f(1,2): " << matrix3f(1,2) << endl << endl;

    MyMatrix1f<double> ret = matrix3f*matrix1f;
    ret.print();

    return 0;
}

運行結果:
2       4       1
matrix1f(1): 4

0.5             -0.866025               10
0.866025        0.5             	20
0               0               	1
matrix3f(1,2): 20

7.5359  23.7321 1
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章