向量(vector)
向量(vector)是表示可以改变大小的数组的序列容器。
就像数组一样,向量使用连续的存储位置作为元素,这意味着它们的元素也可以使用常量指向其元素的偏移来访问,并且与数组一样有效。但与数组不同是向量的大小可以动态变化,其存储由容器自动处理。
在内部,向量使用动态分配的数组来存储它们的元素。可能需要重新分配此数组,以便在插入新元素时增大大小,这意味着分配新数组并将所有元素移动到该数组。就处理时间而言,这是相对昂贵的任务,因此,每次将元素添加到容器时,向量都不会重新分配。
相反,矢量容器可以分配一些额外的存储空间以适应可能的增长,因此容器的实际容量可能大于包含其元素所需的存储容量(即,其大小)。库可以实现不同的增长策略以在内存使用和重新分配之间取得平衡,但无论如何,重新分配只应以对数增长的大小间隔发生,以便在向量末尾插入单个元素可以提供摊销的常量时间复杂性(见push_back)。
因此,与数组相比,向量消耗更多内存,以换取管理存储和以有效方式动态增长的能力。
与其他动态序列容器(deques,lists和forward_lists)相比,向量非常有效地访问其元素(就像数组一样)并且相对有效地从其末尾添加或删除元素。对于涉及在末尾以外的位置插入或删除元素的操作,它们的性能比其他位置差,并且与列表和forward_lists相比具有更少的一致的迭代器和引用。
容器属性
1. 序列
序列容器中的元素按严格的线性顺序排序。 各个元素按其顺序访问它们的位置。
2. 动态数组
允许直接访问序列中的任何元素,甚至通过指针算术,并在序列的末尾提供相对快速的元素添加/删除。
3. 分配器
容器使用allocator对象来动态处理其存储需求。
构造函数:
C++11中vector的构造函数有如下:
1. default
explicit vector (const allocator_type& alloc = allocator_type());
2. fill
explicit vector (size_type n);
vector (size_type n, const value_type& val, const allocator_type& alloc = allocator_type());
3. range
template <class InputIterator>
vector (InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type());
4. copy
vector (const vector& x);
vector (const vector& x, const allocator_type& alloc);
5. move
vector (vector&& x);
vector (vector&& x, const allocator_type& alloc);
6. initializer list
vector (initializer_list<value_type> il, const allocator_type& alloc = allocator_type());
// constructing vectors
#include <iostream>
#include <vector>
int main ()
{
using namespace std;
// constructors
vector<int> one; // empty vector of ints
vector<int> two (4, 10); // 4 ints with value 10
vector<int> three (two.begin(), two.end()); // iterating through two
vector<int> four(three); // a copy of three
// construct from arrays:
int myarray[] = {1, 2, 3, 4, 5};
vector<int> five (myarray, myarray + sizeof(myarray) / sizeof(int) );
cout << "contents of five are:";
for (vector<int>::iterator it = five.begin(); it != five.end(); ++it)
{
cout << ' ' << *it;
}
cout << endl;
return 0;
}
Iterators:
begin
将迭代器返回到开头(公共成员函数)
end
将迭代器返回到end(公共成员函数)
rbegin
返回反向迭代器以反向开始(公共成员函数)
rend
将反向迭代器返回到反向结束(公共成员函数)
cbegin
将const_iterator返回到开头(公共成员函数)C++11
cend
将const_iterator返回到end(公共成员函数)C++11
crbegin
返回const_reverse_iterator以反向开始(公共成员函数)C++11
crend
将const_reverse_iterator返回到反向结束(公共成员函数)C++11
//Iterators:
// vector::begin/end
// vector::rbegin/rend
// vector::cbegin/cend
// vector::crbegin/crend
#include <iostream>
#include <vector>
int main ()
{
using namespace std;
vector<int> vec = {1, 2, 3, 4, 5};
for(auto it=vec.cbegin(); it != vec.cend(); ++it)
{
cout << " " << *it;
}
cout << endl;
for(auto it=vec.crbegin(); it != vec.crend(); ++it)
{
cout << " " << *it;
}
cout << endl;
for(auto it=vec.begin(); it != vec.end(); ++it)
{
cout << " " << *it;
*it *= 2;
}
cout << endl;
for(auto it=vec.rbegin(); it != vec.rend(); ++it)
{
cout << " " << *it;
}
cout << endl;
return 0;
}
Capacity:
size
返回大小(公共成员函数)
max_size
返回最大大小(公共成员函数)
resize
更改大小(公共成员函数)
capacity
返回已分配存储容量的大小(公共成员函数)
empty
返回vector是否为空(公共成员函数)
reverse
请求更改容量(公共成员函数)
shrink_to_fit
缩小到适合的大小(公共成员函数)C++11
//Capacity:
// vector::capacity
// vector::reserve
// vector::resize
// vector::shrink_to_fit
// vector::size
// vector::empty
#include <iostream>
#include <vector>
int main ()
{
using namespace std;
int sz;
vector<int> foo;
/*
size_type capacity() const noexcept;
*/
sz = foo.capacity();
cout << "making foo grow:\n";
for (int i=0; i<100; ++i)
{
foo.push_back(i);
if (sz!=foo.capacity())
{
sz = foo.capacity();
cout << "i=" << i << ", capacity changed: " << sz << endl;
}
}
vector<int> vec(100);
cout << "1. capacity of vec: " << vec.capacity() << endl;
/*
void resize (size_type n);
void resize (size_type n, const value_type& val);
*/
vec.resize(10);
cout << "2. capacity of vec: " << vec.capacity() << endl;
//size_type size() const noexcept;
cout << "2. size of vec: " << vec.size() << endl;
//size_type max_size() const noexcept;
cout << "2. max_size of vec: " << vec.max_size() << endl;
//void shrink_to_fit();
vec.shrink_to_fit();
cout << "3. capacity of vec: " << vec.capacity() << endl;
//void reserve (size_type n);
vec.reserve(300);
cout << "4. capacity of vec: " << vec.capacity() << endl;
vec.clear();
//bool empty() const noexcept;
if(vec.empty())
{
cout << "5. current vec is empty" << endl;
}
return 0;
}
Element access:
operator[]
访问元素(公共成员函数)
at
访问元素(公共成员函数)
front
访问第一个元素(公共成员函数)
back
访问最后一个元素(公共成员函数)
data
访问数据(公共成员函数)
//Element access:
// vector::operator[]
// vector::data
// vector::at
// vector::front
// vector::back
#include <iostream>
#include <vector>
int main ()
{
using namespace std;
vector<int> vec(5);
//vector::operator[]
for(int i=0; i<vec.size(); ++i)
{
vec[i] = i;
}
for(auto& x: vec)
{
cout << " " << x;
}
cout << endl;
//vector::data
int* p = vec.data();
*p = 10;
++p;
*p = 20;
++p;
*p = 30;
p[2] = 40; //means vec[2+2] = 40;
//vector::at
for(int i=0; i<vec.size(); ++i)
{
cout << ' ' << vec.at(i);
}
cout << endl;
vec.push_back(100);
//vector::front , vector::back
vec.front() = vec.back() - 50;
cout << "vec.front()=" << vec.front() << endl;
cout << "vec.back()=" << vec.back() << endl;
return 0;
}
Modifiers:
assign
分配矢量内容(公共成员函数)
push_back
在最后添加元素(公共成员函数)
pop_back
删除最后一个元素(公共成员函数)
insert
插入元素(公共成员函数)
erase
擦除元素(公共成员函数)
swap
交换内容(公共成员函数)
clear
清除内容(公共成员函数)
emplace
构造并插入元素(公共成员函数) C++11
emplace_back
构造并在最后插入元素(公共成员函数)C++11
//Modifiers:
// vector::assign
// vector::push_back
// vector::pop_back
// vector::emplace/emplace_back
// vector::erase
// vector::empty
// vector::clear
// vector::swap
// vector::insert
#include <iostream>
#include <vector>
int main ()
{
using namespace std;
vector<int> one;
vector<int> two;
//void assign (size_type n, const value_type& val);
one.assign(10, 100); // 10 ints with a value of 100
cout << "Size of one: " << one.size() << endl;
cout << "Value of one: ";
for(auto& value: one)
{
cout << " " << value;
}
cout << endl;
/*
template <class InputIterator>
void assign (InputIterator first, InputIterator last);
*/
two.assign(one.begin()+1, one.end()-1); // the 8 central values of one
//void push_back (const value_type& val);
two.push_back(789);
cout << "Value of two: ";
for(auto& value: two)
{
cout << " " << value;
}
cout << endl;
//void pop_back();
two.pop_back();
cout << "Size of two: " << two.size() << endl;
vector<int> vec = {10,20,30};
/*
template <class... Args>
iterator emplace (const_iterator position, Args&&... args);
*/
auto it = vec.emplace ( vec.begin()+1, 100 );
vec.emplace ( it, 200 );
vec.emplace ( vec.end(), 300 );
/*
template <class... Args>
void emplace_back (Args&&... args);
*/
vec.emplace_back(400);
vec.emplace_back(500);
cout << "vec contains:";
for (auto& x: vec)
{
cout << ' ' << x;
}
cout << endl;
//iterator erase (const_iterator position);
vec.erase(vec.begin()+2);
cout << "vec contains:";
for (auto& x: vec)
{
cout << ' ' << x;
}
cout << endl;
//iterator erase (const_iterator first, const_iterator last);
vec.erase(vec.begin()+1, vec.end()-2);
cout << "vec contains:";
for (auto& x: vec)
{
cout << ' ' << x;
}
cout << endl;
//void swap (vector& x);
vec.swap(two);
//void clear() noexcept;
vec.clear();
//bool empty() const noexcept;
if(vec.empty())
{
//iterator insert (const_iterator position, const value_type& val);
vec.insert(vec.begin(), 123);
}
cout << "vec contains:";
for (auto& x: vec)
{
cout << ' ' << x;
}
cout << endl;
return 0;
}
Allocator:
get_allocator
获取分配器(公共成员函数)
//Allocator:
// vector::get_allocator
//template <class T> class allocator;
#include <iostream>
#include <vector>
int main ()
{
using namespace std;
vector<int> vec;
int * p;
unsigned int i;
// Allocate block of storage for 5 elements:
p = vec.get_allocator().allocate(5);
// Construct objects:
for (i=0; i<5; i++)
{
vec.get_allocator().construct(&p[i], (i+1)*10);
}
cout << "allocated array:";
for (i=0; i<5; i++)
{
cout << ' ' << p[i];
}
cout << endl;
// Destroy objects:
for (i=0; i<5; i++)
{
vec.get_allocator().destroy(&p[i]);
}
//Release block of storage
vec.get_allocator().deallocate(p,5);
return 0;
}