std::inplace_vector

来自cppreference.com
< cpp‎ | container
 
 
 
 
在标头 <inplace_vector> 定义
template<

    class T,
    std::size_t N

> struct inplace_vector;
(C++26 起)

inplace_vector 是具有连续原位存储的可动态调整大小的数组。在对象自身内部存储 T 类型的元素并且适当对齐。内部存储的容量是在编译时固定的,等于 N

各元素连续存储,这表示不仅可以通过迭代器或者随机访问的 operator[] 来访问元素,也可以在指向元素的常规指针上使用偏移量。可以将指向 inplace_vector 元素的指针传递给任何接受指向 C 数组元素指针的函数。

inplace_vector 实现容器 (Container) 可逆容器 (ReversibleContainer) 连续容器 (ContiguousContainer) 序列容器 (SequenceContainer) ,包括大多数可选序列容器操作,但不提供成员函数 push_frontemplace_frontpop_frontprepend_range

对于任意正数 Nstd::inplace_vector<T, N>::iteratorstd::inplace_vector<T, N>::const_iterator 满足常量表达式迭代器 (ConstexprIterator) 的要求。

特化 std::inplace_vector<T, 0> 可平凡复制 (TriviallyCopyable) ,并且为空。同时 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=assignassign_rangeclearemplaceeraseinsertinsert_rangepop_backresize 以及 swap

这些成员函数仅会潜在地使 end 迭代器失效: append_rangeemplace_backpush_backtry_append_rangetry_emplace_backtry_push_backunchecked_emplace_back 以及 unchecked_push_back

模板形参

T-元素的类型。必须满足可移动构造 (MoveConstructible) 可移动赋值 (MoveAssignable)
N-容量,即 inplace_vector 中元素的最大数量(可能为 0)。

成员类型

类型定义
value_typeT
size_typestd::size_t
difference_typestd::ptrdiff_t
referencevalue_type&
const_referenceconst value_type&
pointervalue_type*
const_pointerconst value_type*
iterator由实现定义的指向 value_type老式随机访问迭代器 (LegacyRandomAccessIterator) random_access_iterator
const_iterator由实现定义的指向 const value_type老式随机访问迭代器 (LegacyRandomAccessIterator) 常量表达式迭代器 (ConstexprIterator) (C++26 起)random_access_iterator
reverse_iteratorstd::reverse_iterator<iterator>
const_reverse_iteratorstd::reverse_iterator<const_iterator>

成员函数

构造 inplace_vector
(公开成员函数)
析构 inplace_vector
(公开成员函数)
将值赋给容器
(公开成员函数)
将值赋给容器
(公开成员函数)
将范围的值赋给容器
(公开成员函数)
元素访问
带越界检查访问指定的元素
(公开成员函数)
访问指定的元素
(公开成员函数)
访问第一个元素
(公开成员函数)
访问最后一个元素
(公开成员函数)
直接访问底层连续存储
(公开成员函数)
迭代器
返回指向起始的迭代器
(公开成员函数)
返回指向末尾的迭代器
(公开成员函数)
返回指向起始的逆向迭代器
(公开成员函数)
返回指向末尾的逆向迭代器
(公开成员函数)
大小与容量
检查容器是否为空
(公开成员函数)
返回元素数
(公开成员函数)
[静态]
返回可容纳的最大元素数
(公开静态成员函数)
[静态]
返回当前存储空间能够容纳的元素数
(公开静态成员函数)
改变存储元素的个数
(公开成员函数)
[静态]
预留存储空间
(公开静态成员函数)
通过释放未使用的内存减少内存的使用
(公开静态成员函数)
修改器
插入元素
(公开成员函数)
插入元素范围
(公开成员函数)
原位构造元素
(公开成员函数)
在容器末尾原位构造元素
(公开成员函数)
尝试在容器末尾原位构造元素
(公开成员函数)
无条件在容器末尾原位构造元素
(公开成员函数)
将元素添加到容器末尾
(公开成员函数)
尝试将元素添加到容器末尾
(公开成员函数)
无条件将元素添加到容器末尾
(公开成员函数)
移除末元素
(公开成员函数)
添加元素的范围到末尾
(公开成员函数)
尝试添加元素的范围到末尾
(公开成员函数)
清除内容
(公开成员函数)
擦除元素
(公开成员函数)
交换内容
(公开成员函数)


非成员函数

特化 std::swap 算法
(函数模板)
擦除所有满足特定判别标准的元素
(函数模板)
按照字典顺序比较两个 inplace_vector 的值
(函数模板)

注解

inplace_vector 的元素数量可动态变化,最多到一个固定的容量,这是由于各元素是存储在对象自身内部,这与 std::array 相似。不过与 C 数组或 std::array 必须在初始化时构造全部元素不同,对象是在插入到 inplace_vector 之内时初始化的。

inplace_vector 在不希望进行动态内存分配的情形中非常有用。

功能特性测试标准功能特性
__cpp_lib_inplace_vector202406L(C++26)std::inplace_vector: 具有固定容量的原位存储的可动态调整大小的向量
__cpp_lib_constexpr_inplace_vector202502L(C++26)constexpr std::inplace_vector 用于非平凡元素类型

示例

#include <algorithm>
#include <array>
#include <cassert>
#include <inplace_vector>
 
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) != nullptr);
    assert(v1.back() == 3);
    assert(v1.size() == 4);
    assert(v1.try_push_back(13) == nullptr); // 没有位置
    assert(v1.back() == 3);
    assert(v1.size() == 4);
    v1.clear();
    assert(v1.size() == 0);
    assert(v1.empty());
}

参见

动态的连续数组
(类模板)
(C++11)
固定大小的原位连续数组
(类模板)
双端队列
(类模板)

外部链接

1. inplace_vectorP0843R14 (std::inplace_vector) 的一个参考实现。
2. static_vector — Boost.Container 将 inplace vector 实现为一个具有自己的保证的独立类型。
3. fixed_vector — EASTL 通过一个额外的模板参数实现 inplace vector。
4. small_vector — Folly 也通过一个额外的模板参数实现 inplace vector。
5. stack_alloc — Howard Hinnant 在 std::vector 上模拟 std::inplace_vector 的自定义分配器。