分配器如何创建和销毁数组?

时间:2012-04-19 18:10:59

标签: c++ design-patterns memory memory-management

分配器如何创建和销毁数组,例如

int* someInt = someAllocator(3);

没有分配器的地方就是

int* someInt = new int[3];

分配器负责创建每个元素并确保将调用构造函数。

如果不使用new来编写分配器的内部结构?有人可以提供功能的例子吗?

我不想只使用std :: vector,因为我正在尝试学习分配器如何创建数组。

2 个答案:

答案 0 :(得分:2)

一般内存分配的问题是一个令人惊讶的棘手问题。有些人认为它已经解决了,有些人无法解决;)如果你对内部感兴趣,首先看看Doug Lea's malloc

专用内存分配器通常要简单得多 - 为了简化和性能,它们交换了通用性(例如,通过使大小固定)。但要小心,使用通用内存分配通常比实际程序中特殊分配器的大杂烩更好。

一旦通过内存分配器的“魔法”分配了一块内存,就可以使用placement new在容器中进行初始化。

---编辑---

placement new对“普通”编程没用 - 在实现自己的容器时,只需要将内存分配与对象构造分开。话虽这么说,这是一个使用贴牌新的一个有点人为的例子:

#include <new> // For placement new.
#include <cassert>
#include <iostream>

class A {
public:
    A(int x) : X(x) {
        std::cout << "A" << std::endl;
    }
    ~A() {
        std::cout << "~A" << std::endl;
    }
    int X;
};

int main() {

    // Allocate a "dummy" block of memory large enough for A.
    // Here, we simply use stack, but this could be returned from some allocator.
    char memory_block[sizeof(A)];

    // Construct A in that memory using placement new.
    A* a = new(memory_block) A(33);

    // Yup, it really is constructed!
    assert(a->X == 33);

    // Destroy the object, wihout freeing the underlying memory
    // (which would be disaster in this case, since it is on stack).
    a->~A();

    return 0;

}

打印:

A
~A

---编辑2 ---

好的,这是你如何为阵列做的:

int main() {

    // Number of objects in the array.
    const size_t count = 3;

    // Block of memory big enough to fit 'count' objects.
    char memory_block[sizeof(A) * count];

    // To make pointer arithmetic slightly easier.
    A* arr = reinterpret_cast<A*>(memory_block);

    // Construct all 3 elements, each with different parameter.
    // We could have just as easily skipped some elements (e.g. if we
    // allocated more memory than is needed to fit the actual objects).
    for (int i = 0; i < count; ++i)
        new(arr + i) A(i * 10);

    // Yup, all of them are constructed!
    for (int i = 0; i < count; ++i) {       
        assert(arr[i].X == i * 10);
    }

    // Destroy them all, without freeing the memory.
    for (int i = 0; i < count; ++i)
        arr[i].~A();

    return 0;

}

BTW,如果A有默认构造函数,你可以尝试在所有这样的元素上调用它......

new(arr) A[count];

...但这会打开你真正不想处理的can of worms

答案 1 :(得分:0)

我在这里的第二个例子中已经写过:

How to create an array while potentially using placement new

不同之处在于t_allocator::t_array_record将由分配器而不是客户端管理。