vector如何释放空间的问题

来源:互联网 发布:adobe flash软件下载 编辑:程序博客网 时间:2024/05/22 11:29
#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_lianchen@chen-book1:~$ ./vector_lian v1原始: 0Push 两个元素: 2reserve(100): 100swap: 2v2原始: 0Push 两个元素: 2reserve(100): 100swap function: 2v3原始: 0Push 两个元素: 2reserve(100): 100vector<int>(v3).swap(v3): 2vector<int>().swap(v3): 0chen@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;
  }