C++中的向量 - 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
发布了61 篇原创文章 · 获赞 218 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_34139994/article/details/105233286
今日推荐