std::inplace_vector
| 定义于头文件 <inplace_vector>
|
||
template<
class T,
std::size_t N
> struct inplace_vector;
|
(自 C++26 起) | |
std::inplace_vector 是一个拥有连续就地存储的动态可调整大小数组。类型为 T 的元素被存储并适当对齐在对象内部。内部存储的容量在编译时固定,等于 N。
元素连续存储,这意味着元素不仅可以通过迭代器或随机访问 operator[] 访问,还可以通过指向元素的普通指针的偏移量来访问。指向 inplace_vector 元素的指针可以传递给任何需要指向 C 数组元素的指针的函数。
std::inplace_vector 满足 容器、可逆容器、连续容器 和 序列容器 的要求,包括大多数 可选序列容器要求,但未提供 push_front、emplace_front、pop_front 和 prepend_range 成员函数。
对于任何 N,std::inplace_vector<T, N>::iterator 和 std::inplace_vector<T, N>::const_iterator 满足 ConstexprIterator 的要求。
特化 std::inplace_vector<T, 0> 是 可平凡复制 且为空。std::is_trivially_default_constructible_v<std::inplace_vector<T, 0>> 也是 true。
std::inplace_vector<T, N> 的任何会导致插入超过容量 N 的成员函数会抛出 std::bad_alloc。
对 inplace_vector 的常见操作的复杂度如下:
- 通过
operator[]或at()– 对元素的随机访问:常数 𝓞(1)。 - 在末尾插入或移除单个元素 – 常数: 𝓞(1)。
- 在末尾插入或移除多个元素 – 与插入/移除的元素数量成线性: 𝓞(n)。
- 在开头或中间插入或移除元素 – 与插入/移除的元素数量加上到向量末尾的距离成线性: 𝓞(n)。
迭代器失效
std::inplace_vector
迭代器失效保证与
std::vector
不同:
-
移动
inplace_vector会使所有迭代器失效; -
交换两个
inplace_vector会使所有迭代器失效(在交换过程中,迭代器将继续指向同一数组元素,因此其指向的值可能发生改变)。
以下成员函数可能导致迭代器失效:
operator=
、
assign
、
assign_range
、
clear
、
emplace
、
erase
、
insert
、
insert_range
、
pop_back
、
resize
以及
swap
。
以下成员函数可能仅使
end
迭代器失效:
append_range
、
emplace_back
、
push_back
、
try_append_range
、
try_emplace_back
、
try_push_back
、
unchecked_emplace_back
以及
unchecked_push_back
。
模板参数
| T | - | 元素类型。必须满足 MoveConstructible 和 MoveAssignable 要求。 |
| N | - |
容量,即
inplace_vector
中元素的最大数量(可为
0
)。
|
成员类型
| 类型 | 定义 |
value_type
|
T
|
size_type
|
std::size_t |
difference_type
|
std::ptrdiff_t |
reference
|
value_type&
|
const_reference
|
const value_type&
|
pointer
|
value_type*
|
const_pointer
|
const value_type*
|
iterator
|
实现定义 LegacyRandomAccessIterator 和 random_access_iterator 到 value_type
|
const_iterator
|
实现定义 LegacyRandomAccessIterator, ConstexprIterator 和 random_access_iterator 到 const value_type
|
reverse_iterator
|
std::reverse_iterator<iterator>
|
const_reverse_iterator
|
std::reverse_iterator<const_iterator>
|
成员函数
构造
inplace_vector
(公开成员函数) |
|
析构
inplace_vector
(公开成员函数) |
|
|
为容器赋值
(公开成员函数) |
|
|
为容器赋值
(公开成员函数) |
|
|
将值范围赋值给容器
(公开成员函数) |
|
元素访问 |
|
|
访问指定元素(带边界检查)
(公开成员函数) |
|
|
访问指定元素
(公开成员函数) |
|
|
访问首元素
(公开成员函数) |
|
|
访问最后一个元素
(公开成员函数) |
|
|
直接访问底层连续存储
(公开成员函数) |
|
迭代器 |
|
|
返回指向起始位置的迭代器
(公开成员函数) |
|
|
返回指向末尾的迭代器
(公开成员函数) |
|
|
返回指向起始位置的反向迭代器
(公开成员函数) |
|
|
返回指向末尾的反向迭代器
(公开成员函数) |
|
大小与容量 |
|
|
检查容器是否为空
(公开成员函数) |
|
|
返回元素数量
(公开成员函数) |
|
|
[static]
|
返回可能的最大元素数量
(公开静态成员函数) |
|
[static]
|
返回当前分配存储空间可容纳的元素数量
(公开静态成员函数) |
|
修改存储的元素数量
(公开成员函数) |
|
|
[static]
|
预留存储空间
(公开静态成员函数) |
|
[static]
|
通过释放未使用的内存来减少内存使用量
(公共静态成员函数) |
修饰符 |
|
|
插入元素
(公开成员函数) |
|
|
插入元素范围
(公开成员函数) |
|
|
原地构造元素
(公开成员函数) |
|
|
在末尾就地构造元素
(公开成员函数) |
|
|
尝试在末尾就地构造元素
(公开成员函数) |
|
|
无条件在末尾就地构造元素
(公开成员函数) |
|
|
在末尾添加元素
(公开成员函数) |
|
|
尝试在末尾添加元素
(公开成员函数) |
|
|
无条件在末尾添加元素
(公开成员函数) |
|
|
移除末尾元素
(公开成员函数) |
|
|
将元素范围添加至末尾
(公开成员函数) |
|
|
尝试将元素范围添加到末尾
(公开成员函数) |
|
|
清空内容
(公开成员函数) |
|
|
擦除元素
(公开成员函数) |
|
|
交换内容
(公开成员函数) |
|
非成员函数
|
(C++26)
|
特化
std::swap
算法
(函数模板) |
|
擦除满足特定条件的所有元素
(函数模板) |
|
|
(C++26)
|
按字典序比较两个
inplace_vector
的值
(函数模板) |
备注
inplace_vector 中的元素数量可以动态变化,但不超过固定容量,因为元素存储在对象自身内部,类似于 std::array。然而,元素在插入到 inplace_vector 时才会初始化,这与 C 数组或 std::array 不同,后者在实例化时必须构造所有元素。
inplace_vector 适用于不希望进行动态内存分配的环境。
| 功能特性测试宏 | 值 | 标准 | 特性 |
|---|---|---|---|
__cpp_lib_inplace_vector |
202406L |
(C++26) | std::inplace_vector:具有固定容量的原地存储的动态可调整大小向量
|
202603L |
(C++26) | 改进了 try_push_back() 和 try_emplace_back() 的返回类型。已移除 try_append_range()
| |
__cpp_lib_constexpr_inplace_vector |
202502L |
(C++26) | 对于非平凡元素类型的 constexpr std::inplace_vector
|
示例
#include <algorithm>
#include <array>
#include <cassert>
#include <inplace_vector>
#include <optional>
int main()
{
std::inplace_vector<int, 4> v1{0, 1, 2};
assert(v1.max_size() == 4);
assert(v1.capacity() == 4);
assert(v1.size() == 3);
assert(std::ranges::equal(v1, std::array{0, 1, 2}));
assert(v1[0] == 0);
assert(v1.at(0) == 0);
assert(v1.front() == 0);
assert(*v1.begin() == 0);
assert(v1.back() == 2);
v1.push_back(3);
assert(v1.back() == 3);
assert(std::ranges::equal(v1, std::array{0, 1, 2, 3}));
v1.resize(3);
assert(std::ranges::equal(v1, std::array{0, 1, 2}));
assert(v1.try_push_back(3) != std::nullopt);
assert(v1.back() == 3);
assert(v1.size() == 4);
assert(v1.try_push_back(13) == std::nullopt); // no place
assert(v1.back() == 3);
assert(v1.size() == 4);
v1.clear();
assert(v1.size() == 0);
assert(v1.empty());
}
另请参阅
|
可调整大小的连续数组
(类模板) |
|
|
(C++11)
|
固定大小的就地连续数组
(类模板) |
|
双端队列
(类模板) |
外部链接
| 1. |
inplace_vector
—
P0843R14
(
std::inplace_vector
)的参考实现。
|
| 2. |
static_vector
— Boost.Container 以独立类型实现原位向量,并具有其自身的保证特性。
|
| 3. |
fixed_vector
— EASTL 通过额外模板参数实现原位向量。
|
| 4. |
small_vector
— Folly 同样通过额外模板参数实现原位向量。
|
| 5. |
stack_alloc
— Howard Hinnant 的自定义分配器,在
std::vector
基础上模拟
std::inplace_vector
功能。
|