c – 要选择哪种标准容器(如果有的话)?

前端之家收集整理的这篇文章主要介绍了c – 要选择哪种标准容器(如果有的话)?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我需要一些内存管理,并希望我可以将它基于某个std容器.我的要求是:

>元素只有一个默认构造函数(没有副本,没有移动,没有别的)
>容器可以通过一小块连续的元件扩展(在后面)
>我甚至大致知道我总共需要多少元素,甚至更好,在任何时候我最终需要多少元素.但这些都是估计数.
>我真的不需要迭代器,但获取元素运行数的方法会很方便.

所以,我需要一些可以通过添加块来扩展的东西,比如std :: deque.但是对于std :: deque,我不能保证通过8个元素进行扩展会给我一个连续的块.并且std :: deque没有容量所以我无法从std :: deque中“适应”.

这意味着我必须自己写,对吗? (注意:我不想知道如何写我自己的,但只有我必须).

编辑澄清:只有在每次扩展时获得的元素块必须是连续的,而不是整个容器 – 这显然与其他要求相矛盾.

编辑为jalf所以这是什么:用于“排序”3D点的空间八度树.树节点指的是立方体单元,并形成与使用指针链接的父母和女儿的链接结构.同级节点未链接,但在内存中相邻.预先不知道节点的总数(因为每个最终节点的点数> 1),但是可以获得估计.在树构建期间,当划分非最终节点时,必须获得最多8个新节点的连续块,然后将其链接到树中.移动或复制这些节点会使任何现有链接(指针)无效.

另一个编辑只是为了澄清一些讨论.任何基于std :: vector< T>的设计不得使用resize()和/或reserve().在某些条件下,两者都需要复制或移动T的构造函数.即使从未在这些条件下调用过,代码也无法编译.

解决方法

有一个catch,std :: vector适合你.

它完全是连续的,不仅仅是块状的,而且可以扩展,保持连续(第2点).扩展可能意味着重新分配(因此无效的先前获得的指针/迭代器和移动),但如果您事先知道总大小(第3点),则可以保留()以便不进行重新分配.

给定向量v的迭代器i,您可以通过i – v.begin()获得运行数(位置);类似地,给定一个元素的指针p,由p – & v [0](第4点).

捕获是你的观点1.有emplace_back(),但由于与异常安全相关的原因,std :: vector仍然试图在某处临时构造元素,然后将它们移动到它们的永久位置.

假设你有这门课

struct A
{
    A() { }
    A(A&&) = delete;
    A(const A&) = delete;
};

我可以看到两个解决方法

>派生另一个默认构造的类B而不是复制/移动构造:

struct B : A
{
    B() : A() { }
    B(B&&) : A() { }
    B(const B&) : A() { }
};

>如果你不能这样做,那么创建一个为你做这个的allocator对象:

template<typename T>
struct allocator : std::allocator<T>
{
    using std::allocator<T>::allocator;
    using std::allocator<T>::construct;

    template<typename U>
    void construct(U* p,U&&) { construct(p); }

    template<typename U>
    void construct(U* p,const U&) { construct(p); }

    template<typename U>
    struct rebind { using other = allocator<U>; };
};

template<>
struct allocator<void> : std::allocator<void> { };

两种情况的使用如下所示(live example):

template<typename C,size_t N = 100>
void test()
{
    C c;
    c.reserve(N);
    for (size_t i = 0; i < N; ++i)
        c.emplace_back();
}

int main ()
{
    test<std::vector<B> >();
    test<std::vector<A,allocator <A> > >();
}

请记住,这种方式仍有A的实例被构造然后扔掉.这是使用std :: vector的一个不幸后果.如果A足够小并且其默认构造没有任何奇怪的副作用,这应该不是问题.

如果你仍然需要扩展超出初始reserve(),那么我建议使用这样的向量容器作为块.如果您仍然希望将此元容器视为具有自己的迭代器的单个容器,那么相关的是我自己的join view和它的iterator只是为了一个想法,但这仍然是非常实验性的.我敢打赌Boost也有这个目​​的,但我不是那么熟悉.

猜你在找的C&C++相关文章