#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;
}