vector如何释放空间的问题

#include <iostream>
#include <vector>
using namespace std;
 
template<class T>
void swap(vector<T> &v2)
{
    vector<T>v1(v2);
    v1.swap(v2);
}
 int main()
 {
    vector<int> v1;
    
    cout<<"v1"<<endl;
    cout<<"原始: "<<v1.capacity()<<endl;
    v1.push_back(9);
    v1.push_back(10);
    cout<<"Push 两个元素: "<<v1.capacity()<<endl;
    v1.reserve(100);
    cout<<"reserve(100): "<<v1.capacity()<<endl;
    {
        vector<int>vt(v1);
        vt.swap(v1);
    }
    cout<<"swap: "<<v1.capacity()<<endl;
    
    vector<int> v2;
    cout<<"v2"<<endl;
    cout<<"原始: "<<v2.capacity()<<endl;
    v2.push_back(9);
    v2.push_back(10);
    cout<<"Push 两个元素: "<<v2.capacity()<<endl;
    v2.reserve(100);
    cout<<"reserve(100): "<<v2.capacity()<<endl;
    swap(v2);
    cout<<"swap function: "<<v2.capacity()<<endl;
    
    
    vector<int> v3;
    cout<<"v3"<<endl;
    cout<<"原始: "<<v3.capacity()<<endl;
    v3.push_back(9);
    v3.push_back(10);
    cout<<"Push 两个元素: "<<v3.capacity()<<endl;
    v3.reserve(100);
    cout<<"reserve(100): "<<v3.capacity()<<endl;
    vector<int>(v3).swap(v3);
    cout<<"vector<int>(v3).swap(v3): "<<v3.capacity()<<endl;
    vector<int>().swap(v3);
    cout<<"vector<int>().swap(v3): "<<v3.capacity()<<endl;
    return 0;
 }
 
 


运行:

chen@chen-book1:~$ g++ vector_lian.cpp -o vector_lian
chen@chen-book1:~$ ./vector_lian 
v1
原始: 0
Push 两个元素: 2
reserve(100): 100
swap: 2
v2
原始: 0
Push 两个元素: 2
reserve(100): 100
swap function: 2
v3
原始: 0
Push 两个元素: 2
reserve(100): 100
vector<int>(v3).swap(v3): 2
vector<int>().swap(v3): 0
chen@chen-book1:~$ 

解释:

vector的拷贝构造函数和operator=函数只拷贝begin()到end()的部分,end()到start+end_of_storage部分不会拷贝;而swap函数是原样拷贝,包括capacity部分都会考过来。

平时vector的空间是只增不减的,clear()函数只析构,不释放空间。因此只能用swap函数来释放了。swap之后临时的那个vector应该释放掉,方法是放在花括号中,放在函数中,或者最强大的——用临时对象。并且,用他本身去初始化该临时对象,于是,swap后,vector的容量就等于size,没有多余的空间。


参考【1】:

一、 std::vector 的容量操作
C++ STL 容器 vector 对于容量的操作是只增不减,如下面的代码:
vector<int> v;
v.push_back(12); // capacity: 1
v.push_back(22);// capacity: 1 * 2 = 2
v.push_back(32);// capacity: 2 * 2 = 4
cout << v.capacity() << endl; // 4
v.insert(v.begin(), 12, 86);
cout << v.capacity() << endl; // 15
// 删除第 3 个到倒手第 2 个元素(不含)之间的所有元素
v.erase(v.begin() + 2, v.end() ­ 2);
cout << v.size() << endl; // size: 4
cout << v.capacity() << endl; // 15 <­­­ #1
v.clear();
cout << v.capacity() << endl; // 15 <­­­ #2
v.reserve(0);
cout << v.capacity() << endl; // 15 <­­­ #3

由上面的代码可以看出,不论是删除 vector 中的元素(#1)、甚至 clear 整个容器的内容(#2)、或显式
将 capacity 保留为 0(#3),都无法缩减 vector 中闲置的空间。
二、 std::vector 复制构造不会复制 capacity
如下列代码:
vector<int> v2;
v2.push_back(12);
v2.push_back(28);
cout << v2.capacity() << endl; // 2
v2.reserve(120);
cout << v2.capacity() << endl; // 120
cout << v2.size() << endl; // 2
vector<int> v3(v2);
cout << v3.capacity() << endl; // 2  <­­ #1
  cout << v3.size() << endl; // 2
如上所示,v3 的 capacity 只是 2(#2),即 v2 中的元素个数。
三、通过复制构造和 swap 来释放 vector 容器闲置的内存空间
如下代码:
vector<int> v2;
v2.push_back(12);
v2.push_back(28);
cout << v2.capacity() << endl; // 2
v2.reserve(120);
cout << v2.capacity() << endl; // 120
cout << v2.size() << endl; // 2
vector<int> (v2).swap(v2); // <­­ #1
cout << v2.capacity() << endl; // 2  <­­ #2
为什么可以缩减 v2 的 capacity?
1. vector<int> (v2)调用 vector 的复制构造函数,用 v2 中的元素来构造一个新的、临时对象(无名
对象);
2. 由于是复制构造,所以新的、临时对象的 capacity 是 v2 的元素的个数,所以为 2;
3. 由于成员函数 swap()交换两个容器的一切:包括所有迭代器、size、所有元素甚至 capacity;
4. 经过 swap()后,v2 的 capacity 变成新的、临时对象的 capacity,也即 2,对应的:临时对象的
capacity 变成 120;
2 of 3
轩辕高端 IT 培训中心 www.xuanyuan-soft.cn
5. 由于 vector<int> (v2)创建的临时对象在 vector<int> (v2).swap(v2);这个语句结束后销毁,至此 v2
的 capacity 为 2,原先闲置的空间(120-2 个元素的空间)被释放(随着临时容器对象的销毁而释
放)。
同理,完全清除一个 vector 的所有存储:
vector<int> v2;
v2.push_back(12);
v2.push_back(28);
cout << v2.capacity() << endl; // 2
v2.reserve(120);
cout << v2.capacity() << endl; // 120
cout << v2.size() << endl; // 2
vector<int> ().swap(v2); // <­­ #1
  cout << v2.capacity() << endl; // <­­ #2
1. #1 首先创建一个临时(空)容器,然后与 v2 进行 swap。


参考【2】:

//reserve只增不减

  void reserve(size_type n)
  {
    if (capacity() < n)
    {
      const size_type old_size = size();
      iterator tmp = allocate_and_copy(n, start, finish);
      destroy(start, finish);
      deallocate();
      start = tmp;
      finish = tmp + old_size;
      end_of_storage = start + n;
    }
  }

//拷贝构造只拷贝有用元素

  vector(const vector<T, Alloc>& x)
  {
    start = allocate_and_copy(x.end() - x.begin(), x.begin(), x.end());
    finish = start + (x.end() - x.begin());
    end_of_storage = finish;
  }

//赋值函数也只拷贝有用元素

template <class T, class Alloc>
vector<T, Alloc>& vector<T, Alloc>::operator=(const vector<T, Alloc>& x)
{
  if (&x != this)
  {
    if (x.size() > capacity())
    {
      iterator tmp = allocate_and_copy(x.end() - x.begin(),
                                       x.begin(), x.end());
      destroy(start, finish);
      deallocate();
      start = tmp;
      end_of_storage = start + (x.end() - x.begin());
    }
    else if (size() >= x.size())
    {
      iterator i = copy(x.begin(), x.end(), begin());
      destroy(i, finish);
    }
    else
    {
      copy(x.begin(), x.begin() + size(), start);
      uninitialized_copy(x.begin() + size(), x.end(), finish);
    }
    finish = start + x.size();
  }
  return *this;
}

//clear和erase不释放空间,只是析构

void clear() { erase(begin(), end()); }

  iterator erase(iterator first, iterator last)
  {
    iterator i = copy(last, finish, first);
    destroy(i, finish);
    finish = finish - (last - first);
    return first;
  }

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值