初始化后具有固定容量的 C++ vector

标签 c++ vector

我需要一个具有以下要求的 C++ 容器:

  • 容器可以在连续内存中存储不可复制和不可移动的对象。对于 std::vector,对象必须是可复制的或可移动的。
  • 容器的容量在运行时的构建过程中是已知的,并且在销毁之前是固定的。所有需要的内存空间都是在构造期间分配的。对于 boost::static_vector,容量在编译时已知。
  • emplace_back 容器中有更多元素时,容器的大小会随着时间的推移而增加,但绝不能超过 capacity
  • 由于对象不可复制或移动,因此不允许重新分配。

看来STL和BOOST都没有我需要的容器类型。我也在这方面进行了广泛的搜索,但没有找到答案。所以我实现了一个。

#include <memory>

template<class T>
class FixedCapacityVector {
private:
    using StorageType = std::aligned_storage_t<sizeof(T), alignof(T)>;
    static_assert(sizeof(StorageType) == sizeof(T));
public:
    FixedCapacityVector(FixedCapacityVector const&) = delete;
    FixedCapacityVector& operator=(FixedCapacityVector const&) = delete;
    FixedCapacityVector(size_t capacity = 0):
        capacity_{ capacity },
        data_{ std::make_unique<StorageType[]>(capacity) }
    { }
    ~FixedCapacityVector()
    {
        for (size_t i = 0; i < size_; i++)
            reinterpret_cast<T&>(data_[i]).~T();
    }
    template<class... Args>
    T& emplace_back(Args&&... args) 
    {
        if (size_ == capacity_)
            throw std::bad_alloc{};
        new (&data_[size_]) T{ std::forward<Args>(args)... };
        return reinterpret_cast<T&>(data_[size_++]);
    }
    T& operator[](size_t i) 
    { return reinterpret_cast<T&>(data_[i]); }
    T const& operator[](size_t i) const 
    { return reinterpret_cast<T const&>(data_[i]); }
    size_t size() const { return size_; }
    size_t capacity() const { return capacity_; }
    T* data() { return reinterpret_cast<T*>(data_.get()); }
    T const* data() const { return reinterpret_cast<T const*>(data_.get()); }
private:
    size_t const capacity_;
    std::unique_ptr<StorageType[]> const data_;
    size_t size_{ 0 };
};

我的问题是:

  • 我为什么要手动做这件事?我找不到标准容器。或者我没看对地方?还是因为我想做的事情不符合传统?
  • 手写容器是否正确实现?异常安全、内存安全等怎么样?

最佳答案

它可能无法完全回答问题,但根据以下论文,fixed_capacity_vector 可能会添加到 future 的 C++ 标准中:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0843r1.html

简介

本文提出了 boost::container::static_vector [1] 的现代化版本。也就是说,一个可动态调整大小的 vector ,具有编译时固定容量和连续的嵌入式存储,其中元素存储在 vector 对象本身中。

它的 API 与 std::vector 的 API 非常相似。它是一个连续容器,在末尾(非摊销)插入和移除元素的时间复杂度为 O(1),否则在最坏情况下插入和移除的时间复杂度为 O(size())。与 std::vector 一样,元素在插入时初始化并在移除时销毁。对于普通的 value_types, vector 在 constexpr 函数中是完全可用的。

关于初始化后具有固定容量的 C++ vector ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53932651/

相关文章:

c++ - 如何检索轮廓点 - 使用 opencv 转换为 vector ?

c++ - 存储未初始化的 STL vector ?

c++ - 目标文件是什么样的

c++ - 将 vector 转换为数组

c++ - 实时应用的OpenCV fastNlMeansDenoising的替代方法?

c++ - 在 OpenGL 中使用 vbo 绘制圆柱体

c++ - Qt Creator 错误 : cannot find -lopencv_imgcodecs

c++ - 模板化 vs const 非模板化 vector 没有已知的转换

c++ - vector vs unique_ptr 到 c 风格的函数

java - 如何输出存储在java vector 中的对象的属性?