std::vector<T>的reserve()和resize()

预备概念:

容器:有效元素的存储空间,不包括多余容量;

容量:是为了减少哪些使用连续空间(线性空间)存储元素的容器在增加元素时重新分配内存的次数的一种限制,即当增加元素且剩余空间不足时,按照一定比例多分配出一些空闲空间以备将来再增加元素时使用。多余出来的容量是未经初始化的(注意:并没有调用元素类型的默认构造函数来初始化)。

有效元素:调用元素类型的默认构造函数初始化过的存储空间。

std::vector<T>的size()和capacity()这两个成员函数可以看出容器所辖有效元素空间和容量的区别:



void reserve(size_type n)成员函数:n是用户请求保留的总容量的大小;

reserve()的实现与作用:

(1)如果n大于容器现有的容量(即capacity()),则需要在自由内存区为整个容器重新分配一块新的更大的连续空间,其大小为n*sizeof(T),然后将容器内所有有效元素从旧位置全部拷贝到新位置(调用拷贝构造函数),最后释放旧位置的所有存储空间并调整容器对象的元素位置指示器。

(2)否则什么也不做


注意:除了调用容器的某些方法可以改变容器的大小外,在容器外部没有任何方法可以做到,示例如下:

//使用迭代器在冗余容量的空间上通过赋值来给容器增加元素

std::list<int> li;

std::vector<int> vi;

for(int c=0;c<10;c++)

    li.push_back(c);

vi.reserve(li.size());//预留空间,但是并没有改变容器的大小,预留空间未初始化

std::copy(li.begin(),li.end(),vi.begin());  //拷贝赋值

std::copy(vi.begin(),vi.end(),std::ostream_iterator<int>(std::cerr,"\t"));

上述程序错误:虽然vi.reserve()为vector预留了内存,但是改变的只是容器的容量。同时在copy()算法中对容器元素赋值也不会改变容器的大小,因此拷贝过后容器的size()仍然为0,虽然list的元素已经被拷贝到了vector预留空间上。结果:没有输出任何东西;vector在拷贝前后的状态变化如下图:



resize()的实现与作用

void resize(size_type n, const T&c = T());

n是最后要保留的元素个数,c是新增元素的默认初始值。

resize()的实现策略:

(1)如果n 大于容器当前的大小(即siez()),则在容器的末尾插入(追加)n-size()个初值为C的元素,如果不指定初值,则用元素类型的默认构造函数来初始化每一个新元素(可能引起内存重分配以及容器容量的扩张);

(2)如果n小于容器当前的大小,则从容器的末尾删除size() - n个元素,但不释放元素本身的内存空间,因此容量不变。

(3)否则什么也不做。

resize()和赋值操作及insert()、push_back()等都可以合作。

上例改写如下:

std::list<int> li;

std::vector<int> vi;

for(int c = 0;c < 10; c++){

    li.push_back(c);

}

vi.resize(li.size());  //调整容器大小

std::copy(li.begin(),li.end(),vi.begin());  //拷贝赋值

std::copy(vi.begin(),vi.end(),std::ostream_iterator<int>(std::cerr,"\t"));

//可以输出正确结果

resize之后(图一)和拷贝后结构图(图二)如下:







    





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
写一个在vs2019上能运行的#include <iostream>#include <stdlib.h>using namespace std;template <typename T>class Vector{public: Vector() : m_size(0), m_capacity(0), m_data(nullptr) {} Vector(int n, const T& val) : m_size(0), m_capacity(0), m_data(nullptr) { assign(n, val); } Vector(const Vector& other) : m_size(0), m_capacity(0), m_data(nullptr) { assign(other); } Vector& operator=(const Vector& other); T& operator[](int i) { return m_data[i]; } const T& operator[](int i) const { return m_data[i]; } void push_back(const T& val); void insert(int pos, const T& val); void clear(); int size() const { return m_size; } bool empty() const { return m_size == 0; } void erase(int pos);private: void assign(int n, const T& val); void assign(const Vector& other); void reserve(int n); void resize(int n); void destroy();private: int m_size; int m_capacity; T* m_data;};template <typename T>Vector<T>& Vector<T>::operator=(const Vector<T>& other){ if (this != &other) { destroy(); assign(other); } return *this;}template <typename T>void Vector<T>::push_back(const T& val){ if (m_size == m_capacity) { reserve(max(2 * m_capacity, 1)); } m_data[m_size++] = val;}template <typename T>void Vector<T>::insert(int pos, const T& val){ if (pos < 0 || pos > m_size) { return; } if (m_size == m_capacity) { reserve(max(2 * m_capacity, 1)); } for (int i = m_size - 1; i >= pos; i--) { m_data[i + 1] = m_data[i]; } m_data[pos] = val; m_size++;}template <typename T>void Vector<T>::clear(){ destroy(); m_size = 0;}template <typename T>void Vector<T>::erase(int pos){ if (pos < 0 || pos >= m_size) { return; } for (int i = pos; i < m_size - 1; i++) { m_data[i] = m_data[i + 1]; } m_size--;}template <typename T>void Vector<T>::assign(int n, const T& val){ resize(n); for (int i = 0; i < m_size; i++) { m_data[i] = val; }}template <typename T>void Vector<T>::assign(const Vector<T>& other){ resize(other.m_size); for (int i = 0; i < m_size; i++) { m_data[i] = other.m_data[i]; }}template <typename T>void Vector<T>::reserve(int n){ if (n <= m_capacity) { return; } T* new_data = new T[n]; for (int i = 0; i < m_size; i++) { new_data[i] = m_data[i]; } delete[] m_data; m_data = new_data; m_capacity = n;}template <typename T>void Vector<T>::resize(int n){ reserve(n); if (n >= m_size) { for (int i = m_size; i < n; i++) { m_data[i] = T(); } } m_size = n;}template <typename T>void Vector<T>::destroy(){ if (m_data != nullptr) { delete[] m_data; m_data = nullptr; m_capacity = 0; }}int main(){ Vector<int> vec; cout << "push_back 1, 2, 3" << endl; vec.push_back(1); vec.push_back(2); vec.push_back(3); cout << "size: " << vec.size() << endl; cout << "empty: " << vec.empty() << endl; cout << "insert 0 at pos 0" << endl; vec.insert(0, 0); cout << "size: " << vec.size() << endl; cout << "erase at pos 1" << endl; vec.erase(1); cout << "size: " << vec.size() << endl; cout << "clear" << endl; vec.clear(); cout << "size: " << vec.size() << endl; cout << "empty: " << vec.empty() << endl; return 0;}
04-24

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值