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

@H_403_1@我需要一些内存管理,并希望我可以将它基于某个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++类中,有6个默认成员函数: 构造函数 析构函数 拷贝...
#pragma once // 1. 设计一个不能被拷贝的类/* 解析:拷贝只会放生在两个场景中:拷贝构造函数以及赋值运...
C类型转换 C语言:显式和隐式类型转换 隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译...
//异常的概念/*抛出异常后必须要捕获,否则终止程序(到最外层后会交给main管理,main的行为就是终止) try...
#pragma once /*Smart pointer 智能指针;灵巧指针 智能指针三大件//1.RAII//2.像指针一样使用//3.拷贝问...
目录&lt;future&gt;future模板类成员函数:promise类promise的使用例程:packaged_task模板类例程...