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) 的要求。

如果 N > 0std::is_trivial_v<T>false,那么 inplace_vector 的成员函数都不可用于常量表达式

特化 std::inplace_vector<T, 0>平凡类型 (TrivialType) ,也为空。

std::inplace_vector<T, N> 的任何将导致其大小超出 N 的成员函数都抛出 std::bad_alloc 类型的异常。

inplace_vector 上一般操作的复杂度(效率)如下:

  • 随机访问 - 常数 𝓞(1)
  • 末尾的元素插入与移除 - 均摊常数 𝓞(1)
  • 元素的插入与移除 - 与到向量末尾的距离成线性 𝓞(n)

迭代器失效

std::inplace_vector 迭代器的失效保证与 std::vector 的不同:

  • 移动 inplace_vector 会使所有迭代器失效;
  • 交换两个 inplace_vector 会使所有迭代器失效(交换过程中,迭代器会继续指向相同的数组元素,并可能改变其值)。

这些成员函数潜在地会使迭代器失效:resizepop_backeraseswap

模板形参

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 由实现定义的指向 value_type老式随机访问迭代器 (LegacyRandomAccessIterator) random_access_iterator
const_iterator 由实现定义的指向 const value_type老式随机访问迭代器 (LegacyRandomAccessIterator) random_access_iterator
reverse_iterator std::reverse_iterator<iterator>
const_reverse_iterator std::reverse_iterator<const_iterator>

成员函数

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


非成员函数

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

注解

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


功能特性测试 标准 功能特性
__cpp_lib_inplace_vector 202406L (C++26) 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)
固定大小的原位连续数组
(类模板)
双端队列
(类模板)

外部链接

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