allocated memory and arrays

Hello So I'm experimenting with creating objects and arrays with preallocated memory. For instance I have this following code:

int * prealloc = (int*)malloc(sizeof(Test));

Test *arr = new(prealloc) Test();

Where test is defined as follows:

class Test {
public:
    Test() {
        printf("In Constructorn");
    }
    ~Test() {
        printf("In Destructorn");
    }

    int val;
};

In this scenario if I call delete it will actually release the memory which is bad, b/c maybe I'm using some type of memory manager so this will sure cause some problems. I searched in the internet and the only solution that I found was to call the destructor explicitly and then call free:

arr->~Test();
free(arr);

Is there another way to do this? is there perhaps a way to call delete and tell it to just call the destructor and not to release the memory?

My second problem was when working with arrays, like the previous example you can pass to new the pre-allocated memory:

int * prealloc2 = (int*)malloc(sizeof(Test) * 10);
Test *arr2 = new(prealloc2) Test[10];

If I call delete[] it will not only call the destructor for each element in the array but it will also release the memory which is something I don't want. The only way I have found that it should be done is to go through the array and call the destructor explicitly, and then call free. Like with the regular none array operators is there a way to tell the operator to just call the destructors without releasing the memory?

One thing I did notice was that the new operator for an array will actually use the first 4 bytes to store the size of the array (I only tested this in visual studio with a 32 bit build) That would help me know how many elements the array has but there is still one problem. What if the array is a pointer array? for example:

Test **arr2 = new Test*[10];

Could someone help me out with these questions please.


It's normal and expected to directly invoke the destructor to destroy objects you've created with placement new. As far as any other way to do things, about the only obvious alternative is to use an Allocator object (which, at least 99% of the time, will just be a wrapper around placement new and directly invoking the destructor).

Generally speaking, you do not want to use new[] at all. You typically want to allocate your raw memory with operator new (or possibly ::operator new ) and release it with the matching operator delete or ::operator delete .

You create objects in that memory with placement new and destroy them by directly invoking the destructor.


There is no other way to do it but to explicitly call the destructor as delete will also attempt to free the memory.

Using preallocated memory with placement new should be fairly rare in your code - a typical use case is when you're dealing with direct memory mapped hardware interfaces when you want/need to map an object on top of a fixed memory address - and is something I'd normally consider a code smell.

If you want to tweak the memory management for a specific class, you're much better off either using an STL container with a custom allocator or overload operators new and delete for that specific class.


Yes, this is the only way to do it. There is an asymmetry in being allowed to define new but not delete . [ Well, you can do the latter but it can only get called when new throws an exception (not handled properly below!)

You can use a templated destroy to achieve the same result:

class Test 
{
public:
    Test() {
        printf("In Constructorn");
    }
    ~Test() {
        printf("In Destructorn");
    }

    int val;
};

class Allocator
{
public:
    static void* allocate(size_t amount) { return std::malloc(amount);}
    static void unallocate(void* mem) { std::free(mem);}
    static Allocator allocator;
};

Allocator Allocator::allocator;

inline void* operator new(size_t size,  const Allocator& allocator)
{
    return allocator.allocate(size);
}


template<class T>
void destroy(const Allocator& allocator, T* object) 
{ 
    object->~T();
    allocator.unallocate(object);
}




int main()
{
    Test* t = new (Allocator::allocator) Test();

    destroy(Allocator::allocator, t);

    return 0;
}
链接地址: http://www.djcxy.com/p/73036.html

上一篇: 我如何以便携方式自动检测C ++中的内存泄漏?

下一篇: 分配的内存和数组