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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章