用于插入的指针包装器

Posted

技术标签:

【中文标题】用于插入的指针包装器【英文标题】:Pointer wrapper for insertion 【发布时间】:2019-07-18 09:08:58 【问题描述】:

谁能告诉我C++/STL中是否有一种数据类型可以让我轻松解决以下问题:

我有一个预分配的连续内存区域,表示 T 类型的对象数组。 我有一个指向该区域的原始指针 ptrEnd,它指向该区域的最后一个对象之后。 我有一个指针 ptrCurrent 指向该区域内的某个位置。

现在我想要的是某种包装类,它可以帮助我将新元素插入该区域。它应该有某种“附加”功能,基本上做以下事情

将 *ptrCurrent 赋值为要插入的对象的值 将 ptrCurrent 增加一。 如果 ptrCurrent >= ptrEnd,则省略上述步骤。改为返回错误(或返回 false 表示失败)。

我可以自己写这样的东西,但我想先问一下 C++ STL 中是否有一个类可以让我更优雅地解决这个问题。

感谢您的帮助。

【问题讨论】:

STL 类中没有你想要的“错误返回”,所以我想你必须自己写一个,但这应该不难。 你的意思可能不是the stl。 C++ 标准库。随便。 【参考方案1】:

C++17 中有一个方便的特性,多态分配器。更具体地说,这就是你想要的:

std::pmr::monotonic_buffer_resource buffer(sizeof(T) * 256);
    // Buffer that can hold 256 objects of type `T`.

std::pmr::vector<T> vec(&buffer);
    // The vector will use `buffer` as the backing storage.

live godbolt.org example

【讨论】:

我没有 C++17,我必须使用 C++11。另外,我无法控制缓冲区的分配,我只有从外部库接收到的原始指针。 当你推得更多时会发生什么? @RinatVeliakhmedov:AFAIK,它是 UB。【参考方案2】:

您需要编写一个Allocator,从您的数组中分发Ts,然后std::vector 可以使用它。

template <typename T>
class ArrayAllocator

    T* current;
    T* end;
public:
    using value_type = T;

    ArrayAllocator(T* start, T* end) : current(start), end(end) 

    T* allocate(size_t n)
    
         if (current + n >= end) throw std::bad_alloc();
         T * result = current;
         current += n;
         return result;
    

    void deallocate(T* what, size_t n)
    
         if (what + n != current) throw std::runtime_error("bad deallocate");
         current = what;
    

    size_t max_size()  return end - current; 
;

您必须立即reserve 全部数量,因为当vector 重新分配时,它需要将旧值复制到新空间中,这将导致“错误释放”。

【讨论】:

是否可以在不使用储备的情况下阻止向量重新分配? 是的,您应该可以全额预订【参考方案3】:

我最终编写了一个 AppendHelper 类,它接受开始和结束指针,否则会重现 std::vector 接口。我意识到将 std::vector 与自定义分配器一起使用意味着无法完全控制何时执行分配和解除分配,因此结果可能与我的初衷有所不同。

【讨论】:

以上是关于用于插入的指针包装器的主要内容,如果未能解决你的问题,请参考以下文章

C++ 智能指针和指针到指针输出 API。模板化的“包装器”

C++3笔记

通过 python 扩展/包装器传递浮点数组指针 – SndObj-library

如何将 OpenCV 的 MatExpr 的 C 包装器的指针输出转换回 MatExpr

包装器和绑定器std::bind和std::function的回调技术

包装器和绑定器std::bind和std::function的回调技术