C++ vector STL 详解

Reference:

C++ STL 之 vector 用法详解
cplusplus docs
STL之vector容器详解

size VS capacity

  • size: number of elements in the vector.
  • capacity: the size of the storage space currently allocated for the vector, expressed in terms of elements.(分配的内存大小,用完时会自动relocate)

reserve

void reserve (size_type n);

 使vector的capacity至少能容纳n个元素。若n比原始capacity值大,重新分配内存使vector的capacity为n;若n小于等于原有capacity,啥也不做。resize改的是capacity。

resize

void resize (size_type n);
void resize (size_type n, const value_type& val);
Resizes the container so that it contains n elements.

若原有size比n大,多出来的部分destroy掉;若size比n小,有指定val值时补val,否则补0。resize改的是size。

std::vector<int> v;
for (int i=0; i<10; i++)
{
    v.push_back(i);
} // v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

v.resize(5); // v = {1, 2, 3, 4, 5}
v.resize(8,100); // v = {1, 2, 3, 4, 5, 100, 100, 100}
v.resize(12); // v = {1, 2, 3, 4, 5, 100, 100, 100, 0, 0, 0, 0}

erase

iterator erase (const_iterator position);
iterator erase (const_iterator first, const_iterator last);
Removes from the vector either a single element (position) or a range of elements ([first,last)).
This effectively reduces the container size by the number of elements removed, which are destroyed.
Because vectors use an array as their underlying storage, erasing elements in positions other than the vector end causes the container to relocate all the elements after the segment erased to their new positions. This is generally an inefficient operation compared to the one performed for the same operation by other kinds of sequence containers (such as list or forward_list).
  1. Reduce size, while capacity remain the same. 改size不动capacity。
  2. Low efficiency. 效率低不推荐。
// erase
vector<int> b = {10, 20, 30, 40, 50};
cout << "\n##### test erase #####\n";
cout << "b size: " << b.size() << "\t b capacity: " << b.capacity() << endl; // 5 5
b.erase(b.begin());
cout << "After erase. b size: " << b.size() << "\t b capacity: " << b.capacity() << endl;// 4 5

erase 只能对size内的element进行操作,在capacity包含但size中不包含的位置是不能erase的,会引起内存错误。

clear

void clear() noexcept;
Clear content
Removes all elements from the vector (which are destroyed), leaving the container with a size of 0.
A reallocation is not guaranteed to happen, and the vector capacity is not guaranteed to change due to calling this function. A typical alternative that forces a reallocation is to use swap:
vector<T>().swap(x);   // clear x reallocating 

size降为0,但capacity不一定会改变。为保险起见,推荐使用swap

vector<int> a = {1, 2, 3};
// test clear
cout << "a size: " << a.size() << "\t a capacity: " << a.capacity() << endl; // 3 3
a.clear();
cout << "a size: " << a.size() << "\t a capacity: " << a.capacity() << endl; // 0 3

使用Swap()进行内存释放

vector的成员函数clear并不会释放内存,故可以使用swap()函数进行内存释放。

vector<int> v(5, 10);
cout << "v size: " << v.size() << "\t v capacity: " << v.capacity() << endl; // 5 5
v.clear();
cout << "v size: " << v.size() << "\t v capacity: " << v.capacity() << endl; // 0 5
vector<int>().swap(v);
cout << "v size: " << v.size() << "\t v capacity: " << v.capacity() << endl; // 0 0

assign

Assigns new contents to the vector, replacing its current contents, and modifying its size accordingly.
vector<int> a = {1, 2, 3};
vector<int> b = {10, 20, 30, 40, 50};
// assign
// usage 1: void assign (InputIterator first, InputIterator last);
// c.assign(beg,end)将[beg,end)一个左闭右开区间的数据赋值给c。
cout << "b size: " << b.size() << "\t b capacity: " << b.capacity() << endl; // 5 5
b.assign(a.begin(), a.begin() + 2);
cout << "After assigin. b size: " << b.size() << "\t b capacity: " << b.capacity() << endl; // 2 5
cout << "print b: ";
for (auto element: b)
{
    cout << element << "\t";
} // 1 2
cout << endl;

// usage 2: void assign (size_type n, const value_type& val);
// c.assign (n, elem)将n个elem的拷贝赋值给c。
vector<int> v;
v.assign(5,10);// v = {5, 5, 5, 5, 5}

find

vector没有查找元素存在性的成员函数,使用顺序容器的通用方法algorithm中的find()函数

// InputIterator find (InputIterator first, InputIterator last, const T& val);
#include <algorithm>    // std::find
vector<int> v = { 1, 2, 3, 4 };
auto it_1 = find(v.begin(), v.end(), 1); // it_1 = v.begin();
autp it_2 = find(v.begin(), v.end(), 9); // it_2 = v.end();

压缩臃肿的vector

很多时候大量的删除数据导致vector的capacity远大于实际使用的size,需要压缩臃肿的vector,将vector压缩到其实际的size大小。注意一个特性:

std::vector<int> v(5, 10); // v = {10, 10, 10, 10, 10}
cout << "v size: " << v.size() << "\t v capacity: " << v.capacity() << endl; // 5 5
v.clear();
v.push_back(1); v = {1}
cout << "v size: " << v.size() << "\t v capacity: " << v.capacity() << endl; // 1 5
std::vector<int> v1(v);
cout << "v1 size: " << v1.size() << "\t v1 capacity: " << v1.capacity() << endl; // 1 1

用一个vector构建另一个vector时会按其实际size构造而不是按capacity。因此我们借助这一特性加上swap()函数,来完成对vector的压缩。

std::vector<int> v(5, 10);
cout << "v size: " << v.size() << "\t v capacity: " << v.capacity() << endl; // 5 5
v.clear();
v.push_back(1);
cout << "v size: " << v.size() << "\t v capacity: " << v.capacity() << endl; // 1 5
vector<int>(v).swap(v);
cout << "v size: " << v.size() << "\t v capacity: " << v.capacity() << endl; // 1 1

这样即可将vector压缩到其实际大小1在C++11中出现了shrink_to_fit()函数实现vector的压缩。

std::vector<int> v(5, 10);
cout << "v size: " << v.size() << "\t v capacity: " << v.capacity() << endl; // 5 5
v.clear();
cout << "v size: " << v.size() << "\t v capacity: " << v.capacity() << endl; // 0 5
v.shrink_to_fit();
cout << "v size: " << v.size() << "\t v capacity: " << v.capacity() << endl; // 0 0
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章