std::vector
向量是表示可以動態改變大小的數組的序列容器。
就像數組一樣,向量為它們的元素使用連續的存儲位置,這意味着它們的元素也可以使用對其元素的常規指針的偏移進行訪問,並且與數組中一樣有效。但是與數組不同的是,它們的大小可以動態地改變,其存儲由容器自動處理。
在內部,向量使用動態分配的數組來存儲它們的元素。這個數組可能需要重新分配,以便在插入新元素時增加大小,這意味着分配一個新數組並將所有元素移動到它。這在處理時間方面是一項相對昂貴的任務,因此,每次向容器添加元素時,向量不會重新分配。
相反,向量容器可以分配一些額外的存儲以適應可能的增長,並且因此容器可以具有大於容納其元素(即其大小)嚴格需要的存儲空間的實際容量。
庫可以實現不同的增長策略,以平衡內存使用和重新分配。但在任何情況下,重新分配只應該以對數增長的大小間隔發生,以便在向量的末端插入單個元素可以提供有平攤的恆定時間復雜度(見push_back)。
因此,與數組相比,向量消耗更多的內存,以便有效地管理存儲和動態增長的能力。
與其他動態序列容器(deques,lists和forward_lists)相比,向量非常有效地訪問其元素(就像數組),並且相對有效地從其結尾添加或刪除元素。
對於涉及在不同於其他位置的位置插入或刪除元素的操作,它們執行得比其他位置更差。
如果容器為空,則begin()和end()返回的是同一個迭代器,都是尾后迭代器
迭代器失效:改變vector對象容量的操作都會導致迭代器失效
迭代器不能相加。
迭代器相減的結果類型是difference::type,是一個有符號的數。
特性
有序
序列容器中的元素以嚴格的線性順序排列。單個元素按其順序通過其位置訪問。
動態數組
允許直接訪問序列中的任何元素,甚至通過指針算術,並在序列結尾提供相對快速的添加/刪除元素。
自動存儲
容器使用allocator對象動態處理其存儲需求。
vector (constructor)
default (1)
explicit vector (const allocator_type& alloc = allocator_type());
fill (2)
explicit vector (size_type n);
vector (size_type n, const value_type& val,
const allocator_type& alloc = allocator_type());
range (3)
template <class InputIterator>
vector (InputIterator first, InputIterator last,
const allocator_type& alloc = allocator_type());
copy (4)
vector (const vector& x);
vector (const vector& x, const allocator_type& alloc);
move (5)
vector (vector&& x);
vector (vector&& x, const allocator_type& alloc);
initializer list (6)
vector (initializer_list<value_type> il,
const allocator_type& alloc = allocator_type());
代碼舉例
#include <iostream> #include <vector> int main() { std::vector<int> first; // default(1) std::vector<int> second(4, 100); // fill(2) std::vector<int> third(second.begin(), second.end()); // range(3) std::vector<int> fourth(third); // copy(4) // the iterator constructor can also be used to construct from arrays: int myints[] = {16,2,77,29}; std::vector<int> fifth(myints, myints + sizeof(myints) / sizeof(int)); std::cout << "The contents of fifth are:"; for (std::vector<int>::iterator it = fifth.begin(); it != fifth.end(); ++it) std::cout << ' ' << *it; std::cout << '\n'; return 0; }
Output: The contents of fifth are: 16 2 77 29
std::vector::operator=
將新內容分配給容器,替換其當前內容,並相應地修改其大小。
任何在容器中的元素被訪問前都會陪分配或銷毀。
#include <iostream> #include <vector> int main() { std::vector<int> foo(3, 0); std::vector<int> bar(5, 0); bar = foo; foo = std::vector<int>(); std::cout << "Size of foo: " << int(foo.size()) << '\n'; std::cout << "Size of var: " << int(bar.size()) << '\n'; return 0; }
Output: Size of foo: 0 Size of bar: 3
std::vector::assign
將新內容分配給向量,替換其當前內容,並相應地修改其大小。
在調用之前,容器中保存的任何元素都被銷毀,並被新構造的元素替換(元素的賦值不發生)。
這將導致所分配的存儲空間的自動重新分配,當且僅當新的向量大小超過當前的向量容量。
// vector assign #include <iostream> #include <vector> int main () { std::vector<int> first; std::vector<int> second; std::vector<int> third; first.assign(7, 100); // 7 ints with a value of 100 std::vector<int>::iterator it; it=first.begin() + 1; second.assign(it,first.end() - 1); // the 5 central values of first int myints[] = {1776, 7, 4}; third.assign(myints, myints + 3); // assigning from array. std::cout << "Size of first: " << int (first.size()) << '\n'; std::cout << "Size of second: " << int (second.size()) << '\n'; std::cout << "Size of third: " << int (third.size()) << '\n'; return 0; }
Output: Size of first: 7 Size of second: 5 Size of third: 3
operator= 與 assign 區別
相同點:operator=與assign都是釋放原來的內存空間,並分配新的內存空間
不同點:assign返回值為none operator=返回值為*this
Vector Iterators
begin() Return iterator to beginning
end() Return iterator to end
rbegin() Return reverse iterator to reverse beginning
rend() Return reverse iterator to reverse end
cbegin() Return const_iterator to beginning
cend() Return const_iterator to end
crbegin() Return const_reverse_iterator to reverse beginning
crend() Return const_reverse_iterator to reverse end
std::vector::cbegin/cend
返回指向容器中首元素的迭代器
返回指向容器中尾元素下一個元素的迭代器
返回的const_iterator所指的對象值不能改變。
// vector::cbegin/cend #include <iostream> #include <vector> int main () { std::vector<int> myvector = {10, 20, 30, 40, 50}; std::cout << "myvector contains:"; for (auto it = myvector.cbegin(); it != myvector.cend(); ++it) std::cout << ' ' << *it; std::cout << '\n'; return 0; }
Output: myvector contains: 10 20 30 40 50
std::vector::size Return size
std::vector::capacity Return size of allocated storage capacity
std::vector::max_size Return maximum size
// comparing size, capacity and max_size #include <iostream> #include <vector> int main () { std::vector<int> myvector; // set some content in the vector: for (int i=0; i < 100; i++)
myvector.push_back(i);
std::cout << "size: " << myvector.size() << "\n"; std::cout << "capacity: " << myvector.capacity() << "\n"; std::cout << "max_size: " << myvector.max_size() << "\n"; return 0; }
A possible output for this program could be: size: 100 capacity: 128 max_size: 1073741823
size 返回實際容量
capacity 返回默認容量
max_size 返回向量可以容納的最大元素數,這個max_size由系統或庫限制。但容器絕對不能保證能夠達到該尺寸,因為在達到該大小之前的任何時間點仍然無法分配存儲空間。
std::vector::empty Test whether vector is empty
std::vector::operator[]
Return a reference to the element at position n in the vector container.
// vector::operator[] #include <iostream> #include <vector> int main () { std::vector<int> myvector (10); // 10 zero-initialized elements std::vector<int>::size_type sz = myvector.size(); // assign some values: for (unsigned i = 0; i < sz; i++)
myvector[i] = i; // reverse vector using operator[]: for (unsigned i = 0; i < sz / 2; i++) { int temp; temp = myvector[sz - 1 - i]; myvector[sz - 1 - i] = myvector[i]; myvector[i] = temp; } std::cout << "myvector contains:"; for (unsigned i = 0; i < sz; i++) std::cout << ' ' << myvector[i]; std::cout << '\n'; return 0; }
Output: myvector contains: 9 8 7 6 5 4 3 2 1 0
std::vector::at Access element
std::vector::front Access first element
std::vector::back Access last element.
std::vector::data Access data
Returns a direct pointer to the memory array used internally by the vector to store its owned elements.
// vector::data #include <iostream> #include <vector> int main() { std::vector<int> myvector(5); int* p = myvector.data(); *p = 10; ++p; *p = 20; p[2] = 100; std::cout << "myvector contains:"; for (unsigned i = 0; i < myvector.size(); ++i) std::cout << ' ' << myvector[i]; std::cout << '\n'; return 0; }
myvector contains: 10 20 0 100 0
std::vector::push_back Add element at the end
std::vector::pop_back Delete last element
std::vector::insert Insert elements
通過在指定位置的元素之前插入新元素來擴展向量,通過插入的元素數量有效地增加容器大小。
這將導致所分配的存儲空間的自動重新分配,當且僅當新的向量大小超過當前的向量容量。
由於向量使用數組作為其底層存儲,因此將元素插入到向量端以外的位置會導致容器將位置之后的所有元素重新定位到新位置。與通過其他類型的序列容器(例如list或forward_list)執行相同操作的操作相比,這通常是一個低效的操作。
// inserting into a vector #include <iostream> #include <vector> int main() { std::vector<int> myvector(3, 100); std::vector<int>::iterator it; it = myvector.begin(); it = myvector.insert(it, 200); myvector.insert(it, 2, 300); // "it" no longer valid, get a new one. it = myvector.begin(); std::vector<int> anothervector(2, 400); myvector.insert(it + 2, anothervector.begin(), anothervector.end()); int myarray[] = { 501, 502, 503 }; myvector.insert(myvector.begin(), myarray, myarray + 3); std::cout << "myvector contains:" for (it = myvector.begin(); it < myvector.end(); it++) std::cout << ' ' << *it; std::cout << '\n'; return 0; }
Output: myvector contains: 501 502 503 300 300 400 400 200 100 100 100
std::vector::erase Erase elements
Removes from the vector either a single element (position) or a range of elements ([first,last)).
// erasing from vector #include <iostream> #include <vector> int main () { std::vector<int> myvector; // set some values (from 1 to 10) for (int i = 1; i <= 10; i++) myvector.push_back(i); // erase the 6th element myvector.erase(myvector.begin() + 5); // erase the first 3 elements: myvector.erase(myvector.begin(), myvector.begin) + 3); std::cout << "myvector contains:"; for (unsigned i = 0; i < myvector.size(); ++i) std::cout << ' ' << myvector[i]; std::cout << '\n'; return 0; }
Output: myvector contains: 4 5 7 8 9 10
std::vector::swap Swap content
swap vector
// swap vectors #include <iostream> #include <vector> int main () { std::vector<int> foo (3,100); // three ints with a value of 100 std::vector<int> bar (5,200); // five ints with a value of 200 foo.swap(bar); std::cout << "foo contains:"; for (unsigned i=0; i<foo.size(); i++) std::cout << ' ' << foo[i]; std::cout << '\n'; std::cout << "bar contains:"; for (unsigned i=0; i<bar.size(); i++) std::cout << ' ' << bar[i]; std::cout << '\n'; return 0; }
Output: foo contains: 200 200 200 200 200 bar contains: 100 100 100
std::vector::clear Clear content
clearing vectors
// clearing vectors #include <iostream> #include <vector> int main () { std::vector<int> myvector; myvector.push_back (100); myvector.push_back (200); myvector.push_back (300); std::cout << "myvector contains:"; for (unsigned i=0; i<myvector.size(); i++) std::cout << ' ' << myvector[i]; std::cout << '\n'; myvector.clear(); myvector.push_back (1101); myvector.push_back (2202); std::cout << "myvector contains:"; for (unsigned i=0; i<myvector.size(); i++) std::cout << ' ' << myvector[i]; std::cout << '\n'; return 0; }
Output: myvector contains: 100 200 300 myvector contains: 1101 2202
std::vector::emplace Construct and insert element
構建並添加元素
返回值指向新放置元素的迭代器。
通過在位置插入一個新元素來擴展容器。這個新元素是使用args作為構造的參數來構建的。
這有效地將容器尺寸增加了一個。
分配的存儲空間的自動重新分配發生,當且僅當新的向量大小超過當前的向量容量。
由於向量使用數組作為其底層存儲,因此將元素插入到向量端以外的位置會導致容器將所有位置之后的元素移位到新的位置。與其他類型的序列容器(例如list或forward_list)執行的操作相比,這通常是一個低效的操作。對於直接在最后擴展容器的成員函數,請參閱emplace_back。
如果重新分配發生,則與此容器相關的所有迭代器,指針和引用都將失效。
// vector::emplace #include <iostream> #include <vector> int main () { std::vector<int> myvector = {10,20,30}; auto it = myvector.emplace( myvector.begin() + 1, 100 ); myvector.emplace( it, 200 ); myvector.emplace( myvector.end(), 300 ); std::cout << "myvector contains:"; for (auto& x: myvector) std::cout << ' ' << x; std::cout << '\n'; return 0; }
Output: myvector contains: 10 200 100 20 30 300
std::vector::emplace_back Construct and insert element at the end
在向量的末尾插入一個新的元素,就在其最后一個元素之后。這個新元素是使用args作為構造函數的參數構建的。
這有效地將容器大小增加1,這導致所分配的存儲空間的自動重新分配,當僅當新的向量大小超過當前向量容量時。
// vector::emplace_back #include <iostream> #include <vector> int main () { std::vector<int> myvector = {10,20,30}; myvector.emplace_back (100); myvector.emplace_back (200); std::cout << "myvector contains:"; for (auto& x: myvector) std::cout << ' ' << x; std::cout << '\n'; return 0; }
Output: myvector contains: 10 20 30 100 200