定义于头文件 <vector>
template< class T, | (1) | |
namespace pmr { template <class T> | (2) | (C++17 起) |
1) std::vector
是封装动态数组的顺序容器。
2) std::pmr::vector
是使用多态分配器的模板别名。
元素相继存储,这意味着不仅可通过迭代器,还能用指向元素的常规指针访问元素。这意味着指向 vector 元素的指针能传递给任何期待指向数组元素的指针的函数。 | (C++03 起) |
vector 的存储是自动管理的,按需扩张收缩。 vector 通常占用多于静态数组的空间,因为要分配更多内存以管理将来的增长。 vector 所用的方式不在每次插入元素时,而只在额外内存耗尽时重分配。分配的内存总量可用 capacity() 函数查询。额外内存可通过对 shrink_to_fit() 的调用返回给系统。 (C++11 起)
重分配通常是性能上有开销的操作。若元素数量已知,则 reserve() 函数可用于消除重分配。
vector 上的常见操作复杂度(效率)如下:
- 随机访问——常数 O(1)
- 在末尾插入或移除元素——均摊常数 O(1)
- 插入或移除元素——与到 vector 结尾的距离成线性 O(n)
std::vector
(对于 bool
以外的 T
)满足容器 (Container) 、具分配器容器 (AllocatorAwareContainer) 、序列容器 (SequenceContainer) 、连续容器 (ContiguousContainer) (C++17 起)及可逆容器 (ReversibleContainer) 的要求。
修改器
插入元素
std::vector<T,Allocator>::insert
iterator insert( iterator pos, const T& value ); | (1) | (C++11 前) |
iterator insert( const_iterator pos, const T& value ); | (C++11 起) | |
iterator insert( const_iterator pos, T&& value ); | (2) | (C++11 起) |
void insert( iterator pos, size_type count, const T& value ); | (3) | (C++11 前) |
iterator insert( const_iterator pos, size_type count, const T& value ); | (C++11 起) | |
template< class InputIt > | (4) | (C++11 前) |
template< class InputIt > | (C++11 起) | |
iterator insert( const_iterator pos, std::initializer_list<T> ilist ); | (5) | (C++11 起) |
插入元素到容器中的指定位置。
1-2) 在 pos
前插入 value
。
3) 在 pos
前插入 value
的 count
个副本。
4) 在 pos
前插入来自范围 [first, last)
的元素。
若 InputIt 为整数类型,则此重载与重载 (3) 拥有相同效果。 | (C++11 前) |
此重载仅若 InputIt 足以为遗留输入迭代器 (LegacyInputIterator) 才参与重载决议,以避免与重载 (3) 有歧义。 | (C++11 起) |
若 first
和 last
是指向 *this 中的迭代器,则行为未定义。
5) 在 pos
前插入来自 initializer_list ilist
的元素。
若新 size() 大于旧 capacity() 则导致重分配。 若新的 size() 大于 capacity() ,则所有迭代器和引用都被非法化。否则,仅在插入点前的迭代器和引用保持合法。尾后迭代器亦被非法化。
参数
pos | - | 将内容插入到其前的迭代器。 pos 可为 end() 迭代器 |
value | - | 要插入的元素值 |
first, last | - | 要插入的元素范围,不能是指向调用 insert 所用的容器中的迭代器 |
ilist | - | 要插入的值来源的 initializer_list |
类型要求 | ||
- 为使用重载 (1) , T 必须满足可复制赋值 (CopyAssignable) 和 可复制插入 (CopyInsertable) 的要求。 | ||
- 为使用重载 (2) , T 必须满足可移动赋值 (MoveAssignable) 和 可移动插入 (MoveInsertable) 的要求。 | ||
- 为使用重载 (3) , T 必须满足可复制赋值 (CopyAssignable) 和 可复制插入 (CopyInsertable) 的要求。 | ||
- 为使用重载 (4,5) , T 必须满足可就位构造 (EmplaceConstructible) 的要求。 | ||
- 为使用重载 (4) , T 必须满足可移动赋值 (MoveAssignable) 和 可移动插入 (MoveInsertable) 的要求。仅若 InputIt 满足遗留输入迭代器 (LegacyInputIterator) 但不满足遗留向前迭代器 (LegacyForwardIterator) 才要求。(C++17 前) | ||
- 为使用重载 (4,5) , T 必须满足可交换 (Swappable) 、 可移动赋值 (MoveAssignable) 、 可移动构造 (MoveConstructible) 和 可移动插入 (MoveInsertable) 的要求。(C++17 起) |
返回值
1-2) 指向被插入 value
的迭代器。
3) 指向首个被插入元素的迭代器,或若 count==0 则为 pos
。
4) 指向首个被插入元素的迭代器,或若 first==last 则为 pos
。
5) 指向首个被插入元素的迭代器,或若 ilist
为空则为 pos
。
复杂度
1-2) 常数,加上 pos
与容器结尾的距离成线性。
3) 与 count 成线性,加上 pos
与容器结尾的距离成线性。
4) 与 std::distance(first, last) 成线性,加上 pos
与容器结尾的距离成线性。
5) 与 ilist.size() 成线性,加上 pos
与容器结尾的距离成线性。
异常
若在尾端插入单个元素时抛出异常,且 T 为可复制插入 (CopyInsertable) 或 std::is_nothrow_move_constructible<T>::value 为 true ,则无效果(强异常保证)。
原位构造元素
std::vector<T,Allocator>::emplace
template< class... Args > | (C++11 起) |
直接于 pos
前插入元素到容器中。通过 std::allocator_traits::construct 构造元素,它典型地用布置 new 在容器所提供的位置原位构造元素。将参数 args...
作为 std::forward<Args>(args)... 转发给构造函数。
若新的 size() 大于 capacity() ,则所有迭代器和引用都被非法化。否则,仅在插入点前的迭代器和引用保持合法。尾后迭代器亦被非法化。
参数
pos | - | 将构造新元素到其前的迭代器 |
args | - | 转发给元素构造函数的参数 |
类型要求 | ||
- T (容器元素类型) 必须满足可移动赋值 (MoveAssignable) 、 可移动插入 (MoveInsertable) 和 可就位构造 (EmplaceConstructible) 的要求。 |
返回值
指向被安置的元素的迭代器。
复杂度
与 pos
和容器尾的距离成线性。
异常
若 value_type 的复制构造函数、移动构造函数、赋值运算符或移动赋值运算符以外的操作抛异常,或若在用 emplace
在尾部插入单个元素时抛异常,且 value_type 为可复制插入 (CopyInsertable) 或可不抛出移动构造,则无效果(强异常保证)。
否则,效果未指定。
注意
特化 std::vector<bool> 在 C++14 前无 emplace()
成员。
调用示例
#include <iostream>
#include <string>
#include <iterator>
#include <algorithm>
#include <functional>
#include <time.h>
#include <vector>
struct Cell
{
int x;
int y;
Cell() = default;
Cell(int a, int b): x(a), y(b) {}
Cell &operator +=(const Cell &cell)
{
x += cell.x;
y += cell.y;
return *this;
}
Cell &operator +(const Cell &cell)
{
x += cell.x;
y += cell.y;
return *this;
}
Cell &operator *(const Cell &cell)
{
x *= cell.x;
y *= cell.y;
return *this;
}
Cell &operator ++()
{
x += 1;
y += 1;
return *this;
}
bool operator <(const Cell &cell) const
{
if (x == cell.x)
{
return y < cell.y;
}
else
{
return x < cell.x;
}
}
bool operator >(const Cell &cell) const
{
if (x == cell.x)
{
return y > cell.y;
}
else
{
return x > cell.x;
}
}
bool operator ==(const Cell &cell) const
{
return x == cell.x && y == cell.y;
}
};
std::ostream &operator<<(std::ostream &os, const Cell &cell)
{
os << "{" << cell.x << "," << cell.y << "}";
return os;
}
int main()
{
std::cout << std::boolalpha;
std::mt19937 g{std::random_device{}()};
srand((unsigned)time(NULL));
auto generate = []()
{
int n = std::rand() % 10 + 110;
Cell cell{n, n};
return cell;
};
//3) 构造拥有 count 个有值 value 的元素的容器。
std::vector<Cell> vector1(1, generate());
//替换容器的内容。1) 以 count 份 value 的副本替换内容。
std::cout << "vector1: ";
std::copy(vector1.begin(), vector1.end(), std::ostream_iterator<Cell>(std::cout, " "));
std::cout << std::endl;
std::cout << std::endl;
//插入元素到容器中的指定位置。1-2) 在 pos 前插入 value 。
Cell cell = generate();
std::cout << "iterator insert( iterator pos, const T& value ) : " << std::endl;
vector1.insert(vector1.begin(), cell);
std::cout << "vector1.insert(vector1.begin(), Cell" << cell << " ) " << std::endl;
std::cout << "vector1: ";
std::copy(vector1.begin(), vector1.end(), std::ostream_iterator<Cell>(std::cout, " "));
std::cout << std::endl;
std::cout << std::endl;
//插入元素到容器中的指定位置。1-2) 在 pos 前插入 value 。
cell = generate();
std::cout << "iterator insert( const_iterator pos, const T& value ) : " << std::endl;
vector1.insert(vector1.cbegin(), cell);
std::cout << "vector1.insert(vector1.cbegin(), Cell" << cell << " ) " << std::endl;
std::cout << "vector1: ";
std::copy(vector1.begin(), vector1.end(), std::ostream_iterator<Cell>(std::cout, " "));
std::cout << std::endl;
std::cout << std::endl;
//插入元素到容器中的指定位置。1-2) 在 pos 前插入 value 。
cell = generate();
std::cout << "iterator insert( const_iterator pos, T&& value ) : " << std::endl;
vector1.insert(vector1.cbegin(), std::move(cell));
std::cout << "vector1.insert(vector1.cbegin(), std::move(Cell" << cell << " )) " << std::endl;
std::cout << "vector1: ";
std::copy(vector1.begin(), vector1.end(), std::ostream_iterator<Cell>(std::cout, " "));
std::cout << std::endl;
std::cout << std::endl;
//3) 构造拥有 count 个有值 value 的元素的容器。
std::vector<Cell> vector2(2, generate());
//替换容器的内容。1) 以 count 份 value 的副本替换内容。
std::cout << "vector2: ";
std::copy(vector2.begin(), vector2.end(), std::ostream_iterator<Cell>(std::cout, " "));
std::cout << std::endl;
std::cout << std::endl;
//插入元素到容器中的指定位置。3) 在 pos 前插入 value 的 count 个副本。
cell = generate();
std::cout << "void insert( iterator pos, size_type count, const T& value ): " << std::endl;
vector2.insert(vector2.begin(), 2, cell);
std::cout << "vector2.insert(vector2.begin(), 2, Cell" << cell << " ) " << std::endl;
std::cout << "vector2: ";
std::copy(vector2.begin(), vector2.end(), std::ostream_iterator<Cell>(std::cout, " "));
std::cout << std::endl;
std::cout << std::endl;
//插入元素到容器中的指定位置。3) 在 pos 前插入 value 的 count 个副本。
cell = generate();
std::cout << "void insert( const_iterator pos, size_type count, const T& value ): " << std::endl;
vector2.insert(vector2.cbegin(), 2, cell);
std::cout << "vector2.insert(vector2.cbegin(), 2, Cell" << cell << " ) " << std::endl;
std::cout << "vector2: ";
std::copy(vector2.begin(), vector2.end(), std::ostream_iterator<Cell>(std::cout, " "));
std::cout << std::endl;
std::cout << std::endl;
//3) 构造拥有 count 个有值 value 的元素的容器。
std::vector<Cell> vector3(2, generate());
//替换容器的内容。1) 以 count 份 value 的副本替换内容。
std::cout << "vector3: ";
std::copy(vector3.begin(), vector3.end(), std::ostream_iterator<Cell>(std::cout, " "));
std::cout << std::endl;
std::cout << std::endl;
//插入元素到容器中的指定位置。4) 在 pos 前插入来自范围 [first, last) 的元素。
std::cout << "template< class InputIt >" << std::endl;
std::cout << "void insert( iterator pos, InputIt first, InputIt last)" << std::endl;
vector3.insert(vector3.begin(), vector1.begin(), vector1.end());
std::cout << "vector3.insert(vector3.begin(), vector1.begin(), vector1.end())" << std::endl;
std::cout << "vector3: ";
std::copy(vector3.begin(), vector3.end(), std::ostream_iterator<Cell>(std::cout, " "));
std::cout << std::endl;
std::cout << std::endl;
std::vector<Cell> vector4;
//插入元素到容器中的指定位置。4) 在 pos 前插入来自范围 [first, last) 的元素。
std::cout << "template< class InputIt >" << std::endl;
std::cout << "void insert( const_iterator pos, InputIt first, InputIt last)" << std::endl;
vector4.insert(vector4.begin(), vector1.begin(), vector1.end());
std::cout << "vector4.insert(vector4.begin(), vector1.begin(), vector1.end())" << std::endl;
std::cout << "vector4: ";
std::copy(vector4.begin(), vector4.end(), std::ostream_iterator<Cell>(std::cout, " "));
std::cout << std::endl;
std::cout << std::endl;
std::vector<Cell> vector5;
//插入元素到容器中的指定位置。5) 在 pos 前插入来自 initializer_list ilist 的元素。
std::cout << "void insert( const_iterator pos, std::initializer_list<T> ilist )" << std::endl;
vector5.insert(vector5.begin(), {{101, 102}, {103, 104}, {105, 106}});
std::cout << "vector5.insert(vector5.begin(), {{101, 102}, {103, 104}, {105, 106}})" << std::endl;
std::cout << "vector5: ";
std::copy(vector5.begin(), vector5.end(), std::ostream_iterator<Cell>(std::cout, " "));
std::cout << std::endl;
std::cout << std::endl;
//直接于 pos 前插入元素到容器中。
//通过 std::allocator_traits::construct 构造元素,
//它典型地用布置 new 在容器所提供的位置原位构造元素。
std::vector<Cell> vector6;
std::cout << "template< class... Args >" << std::endl;
std::cout << "iterator emplace( const_iterator pos, Args&&... args )" << std::endl;
std::cout << "vector6.emplace(vector6.begin(),"
<< "std::rand() % 10 + 110, std::rand() % 10 + 110)" << std::endl;
while (vector6.size() < 6)
{
vector6.emplace(vector6.begin(), std::rand() % 10 + 110, std::rand() % 10 + 110);
}
std::cout << "vector6: ";
std::copy(vector6.begin(), vector6.end(), std::ostream_iterator<Cell>(std::cout, " "));
std::cout << std::endl;
return 0;
}
输出