views:

157

answers:

5

This is possibly a candidate for a one-line answer. I would like know it anyway..

I am writing a simple circular buffer and for some reasons that are not important for the question I need to implement it using an array of doubles. In fact I have not investiated other ways to do it, but since an array is required anyway I have not spent much time on looking for alternatives.

template<typename T>
class CircularBuffer
{
public:
    CircularBuffer(unsigned int size);
    ~CircularBuffer();
    void Resize(unsigned int new_size);
    ...
private:
    T* buffer;
    unsigned int buffer_size;
};

Since I need to have the buffer dynamically sized the buffer_size is neither const nor a template parameter. Now the question:

During construction and in function Resize(int) I only require the size to be at least one, although a buffer of size one is effectively no longer a buffer. Of course using a simple double instead would be more appropriate but anyway.

Now when deleting the internal buffer in the destructor - or in function resize for that matter - I need to delete the allocated memory. Question is, how? First candidate is of course delete[] buffer; but then again, if I have allocated a buffer of size one, that is if the pointer was aquired with buffer = new T[0], is it still appropriate to call delete[] on the pointer or do I need to call delete buffer; (without brackets) ?

Thanks, Arne

+8  A: 

If you allocate the memory with new T[x], you always delete it with delete[], even if x ≤ 1.

KennyTM
+1 Thanks! Sometimes it's so surprisingly simple!
Arne
+3  A: 

Only use delete[] on addresses returned by new[] - regardless of the buffer size. Using delete in this case is undefined behavior.

sharptooth
+1  A: 

buffer of size 1 should be allocated as buffer = new T[1] and then delete[] buffer should be used. No need to differentiate as n =1 as special case. Thumb rule :: every new [] should have corresponding delete []

aJ
+6  A: 

Why not use a vector?

obelix
+1 That's the most sensible answer to all such questions: Simply avoid manual memory management altogether. What does it buy you over a `std::vector`?
sbi
Well, as I said I do *need* to use an array. This is because I need to integrate with some code that uses pointers to certain elements for monitoring and I need to guarantee that for example the most recent elment stays at the same memory address during the lifetime of the CircularBuffer object.
Arne
@Arne: you have that guarantee if you don't change your vector. You also don't have that guarantee if you reallocate your array.
stefaanv
@stefaanv I just realized that issue myself, but thanks anyway.
Arne
this would be more helpful as a comment. It's a perfectly good suggestion, but it doesn't answer his question
jalf
It actually does answer his question, as std::vector must _contain_ an array. (contiguous element requirement).
MSalters
A: 

When you use "delete[]" it knows that it must delete an array of objects - it calls each destructor of the objects in the array. Do not slip away from the standard - it will only give you a lot of headaches. When using new use delete. When using new [] use delete []. Just as simple as that.

Iulian Şerbănoiu