A simple test app:
cout << new int[0] << endl;
outputs:
0x876c0b8
So it looks like it works. What does the standard say about this? Is it always legal to "allocate" empty block of memory?
A simple test app:
cout << new int[0] << endl;
outputs:
0x876c0b8
So it looks like it works. What does the standard say about this? Is it always legal to "allocate" empty block of memory?
From 5.3.4/7
When the value of the expression in a direct-new-declarator is zero, the allocation function is called to allocate an array with no elements.
From 3.7.3.1/2
The effect of dereferencing a pointer returned as a request for zero size is undefined.
Also
Even if the size of the space requested [by new] is zero, the request can fail.
That means you can do it, but you can not legally (in a well defined manner across all platforms) dereference the memory that you get - you can only pass it to array delete - and you should delete it.
Here is an interesting foot-note (i.e not a normative part of the standard, but included for expository purposes) attached to the sentence from 3.7.3.1/2
[32. The intent is to have operator new() implementable by calling malloc() or calloc(), so the rules are substantially the same. C++ differs from C in requiring a zero request to return a non-null pointer.]
new[]
with a delete[]
- whatever the size. In particular, when you call new[i]
you need a bit more memory than that which you are trying to alloc in order to store the size of the array (which is later used by delete[]
when deallocating) –
Spaceship Yes, it is legal to allocate a zero-sized array like this. But you must also delete it.
int ar[0];
is illegal why is new OK? –
Perron sizeof (type)
is expected to never return zero. See for example: https://mcmap.net/q/110238/-can-sizeof-return-0-zero –
Spaceship What does the standard say about this? Is it always legal to "allocate" empty block of memory?
Every object has a unique identity, i.e. a unique address, which implies a non-zero length (the actual amount of memory will be silently increased, if you ask for zero bytes).
If you allocated more than one of these objects then you'd find they have different addresses.
operator []
also stores the size of the array somewhere (see isocpp.org/wiki/faq/freestore-mgmt#num-elems-in-new-array). So if the implementation allocates the byte count with the data, it could just allocate for the byte count and 0 bytes for data, returning 1-past-last pointer. –
Macswan operator new[]
should return different pointers. BTW, the new expression
has some additional rules (5.3.4). I couldn't find any clue that new
with 0 size is actually required to allocate anything. Sorry, I downvoted because I find that your answer is not answering the questions, but is providing some controversial statements. –
Macswan new[]
implementation to return addresses in a range where there is no dynamic memory mapped, hence not really using any memory (while using address space) –
Spaceship while(!exitRequested) { char *p = new char[0]; delete [] p; }
loop without recycling pointers would collapse into dust before it could possibly run out of address space, but on a platform with 32-bit pointers that would be a far less reasonable assumption. –
Selfwill new
can be exploited to resolve some aliasing and object identity instead –
Spaceship Yes it is completely legal to allocate a 0
sized block with new
. You simply can't do anything useful with it since there is no valid data for you to access. int[0] = 5;
is illegal.
However, I believe that the standard allows for things like malloc(0)
to return NULL
.
You will still need to delete []
whatever pointer you get back from the allocation as well.
I guarantee you that new int[0] costs you extra space since I have tested it.
For example, the memory usage of
int **arr = new int*[1000000000];
is significantly smaller than
int **arr = new int*[1000000000];
for(int i =0; i < 1000000000; i++) {
arr[i]=new int[0];
}
The memory usage of the second code snippet minus that of the first code snippet is the memory used for the numerous new int[0].
Curiously, C++ requires that operator new return a legitimate pointer even when zero bytes are requested. (Requiring this odd-sounding behavior simplifies things elsewhere in the language.)
I found Effective C++ Third Edition said like this in "Item 51: Adhere to convention when writing new and delete".
© 2022 - 2024 — McMap. All rights reserved.
std::vector<double> v;
constructs an empty vector (zero elements). The default allocator doesn't returnnullptr
(just checked), yet it turn out thatv.data() == nullptr
.This gives the clue that for the special case of no element the default allocator is not used (or, less likely, overwritten). If you trust the wisdom of the standard library (perhaps Stepanov's insight), that means that it is probably not a good idea to try to allocate zero sized dynamic arrays.(new int[0]
uses some memory because the `0 is stored somewhere) – Icarusstruct vector : ..., ptr_(num_elements==0?nullptr:allocator_.allocate(num_elements)), ...{...}
. – Icarus