views:

388

answers:

4

My C++ program needs a block of uninitialized memory and a void* pointer to that block so that I can give it to a third party library. I want to pass control of the block lifetime to the library, so I don't want to use std::vector. When the library is done with the block it will call a callback that I have to supply and that will deallocate the block. In C I would use malloc() and later free().

In C++ I can either call ::operator new or ::operator new[] and ::operator delete or operator delete[] respectively later:

void* newBlock = ::operator new( sizeOfBlock );
// then, later
::operator delete( newBlock );

Looks like both ::operator new and ::operator new[] have exactly the same signature and exactly the same behavior. The same for ::operator delete and ::operator delete[]. The only thing I shouldn't do is pairing operator new with operator delete[] and vice versa - undefined behavior. Other than that which pair do I choose and why?

A: 

for allocating memory to array/list use new[] other than that use new...

mihirpmehta
+7  A: 

Use new with a single object and new[] with an array of objects. So, for example:

int* x = new int; // Allocates single int
int* y = new int[5]; // Allocates an array of integers

*x = 10; // Assignment to single value
y[0] = 8; // Assignment to element of the array

If all you are doing is allocating a memory buffer, then allocate an array of char as in:

int bufferlen = /* choose a buffer size somehow */
char* buffer = new char[bufferlen];
// now can refer to buffer[0] ... buffer[bufferlen-1]

However, in C++, you should really use std::vector for arbitrary arrays, and you should use std::string for character arrays that are to be interpreted or used as strings.

There is no reason to invoke ::operator new or ::operator new[] explicitly rather than using the ordinary syntax for these calls. For POD and primitive types (e.g. char) no initialization will take place. If you need to get a void* buffer, then simply use static_cast to convert char* to void*.

Michael Aaron Safyan
The OP isn't talking about `new int` and `new int[5]`, but specifically calling the functions with the given names, e.g. `void* p = operator new(50);` vs `void* p = operator new[](50);`.
Roger Pate
@Roger, thanks. This wasn't made clear until a later edit.
Michael Aaron Safyan
Your update is slightly wrong. There's a difference between `new int` and `new int()` (the latter object is guaranteed to be initialized to zero), and similarly for any POD type. One special case also works for new[]: `new int[5]()`.
Roger Pate
@Roger, that is correct; however, in the syntax I gave, no initialization takes place.
Michael Aaron Safyan
That's why I said slightly, specifically: "For POD and primitive types (e.g. char) no initialization will take place." You don't make it clear that `new int` is different semantics than `new int()`, but do characterize the whole "ordinary syntax".
Roger Pate
Well, the suggestion to just use new char[] implies that I have to use ::operator new[].
sharptooth
@sharptooth: I believe he's saying you should use a new expression rather than calling operator new directly, not trying to imply anything about operator new vs operator new[]. However, you have considerably changed the question, because as written now you have no choice in how the third party library deallocates, rather than you having sole control yourself as you had before.
Roger Pate
@Roger Pate: Yes, I completely understand his answer. Still I don't want to use the `new` statement simply to avoid casting from `char*` to `void*` and back even if `static_cast` will do the job at no cost. Anyway `new[]` statement implies `::operator new[]` and that more or less answers my question.
sharptooth
+1  A: 

The advantage of the C++ new operators over C's malloc() and free() is that the former throws an exception if there is not enough memory, rather than returning NULL.

Regarding choosing new(size) and new[] for character buffers, I'd advocate the latter since it is less likely to surprise people maintaining the code later i.e. char* buf = new char[size] and delete[] buf.

The values in the buffer will not be initialised, and there is no range-checking - you have to build a nice C++ object to do that for you, or use an existing object such as std::vector or std::string.

Will
+1  A: 

The question cannot be answered sensibly.

Firstly, it is said that the program 'needs' a block of uninitialized memory but, from the code sample given, it seems that the program 'needs' a block of uninitialized and UNTYPED memory which seems not very C++ or OO.

Secondly, a std::vector gives sole and automatic control over a block of typed memory that may or may not change in size according to its use. You can lose this control if an instance of std::vector is created on the heap and tracked with raw pointers just as for any other C or C++ object such as a void* memory block.

Thirdly, what is the intended use of this memory block? The answer to this may or may not dictate the use of operator new or operator new[]. In the design of this program, is there a single interpretation of this memory block? What ownership semantics do you require, if any? Etc, etc.

Sam
Note: These questions were answered in a later edit.
David Thornley