C ++ does not tell you the size of a dynamic array. But why?

I know that in C ++ there is no way to get the size of a dynamically created array, for example:

int* a; a = new int[n]; 

What I would like to know: why? Do people just forget about it in the C ++ spec, or is there a technical reason for this?

Isn't the information stored somewhere? In the end, the team

 delete[] a; 

it seems to know how much memory it should release, so it seems to me that delete[] has some way of knowing the size of a .

+55
c ++ dynamic-arrays
Apr 07 '16 at 8:48
source share
7 answers

You will often find that memory managers will allocate space in a certain amount, for example, 64 bytes.

So, you can request a new int [4], i.e. 16 bytes, but the memory manager will allocate 64 bytes for your request. To free up this memory, you do not need to know how much memory you requested, only that it allocates you one block of 64 bytes.

The next question may be, can it not store the requested size? This is an additional overhead that not everyone is willing to pay. For example, Arduino Uno has only 2 KB of RAM, and in this context, 4 bytes for each allocation suddenly become significant.

If you need this functionality, you have std :: vector (or the equivalent), or you have higher-level languages. C / C ++ was designed so that you can work with as little overhead as you decide to use, which is one example.

+1
Apr 7 '16 at 20:50
source share

The following from the basic rule is "do not pay for what you do not need." In your example, delete[] a; no need to know the size of the array, because int does not have a destructor. If you wrote:

 std::string* a; a = new std::string[n]; ... delete [] a; 

Then delete should call the destructors (and should know how much to call) - in this case new should save this account. However, given that he did not need to be saved in all cases, Bjarn decided not to grant him access.

(Looking back, I think it was a mistake ...)

Even with int , of course, something should know about the size of the allocated memory, but:

  • Many allocators round a size to some convenient set (for example, 64 bytes) for ease of alignment and convenience. The allocator knows that the block is 64 bytes long, but it does not know if this is because n was 1 ... or 16.

  • The C ++ Runtime Library may not have access to the size of the allocated block. If, for example, new and delete use malloc and free under the hood, then the C ++ library does not have the ability to find out the size of the block returned by malloc . (Usually, of course, new and malloc are part of the same library, but not always.)

+33
Apr 7 '16 at 8:57
source share

One fundamental reason is that there is no difference between a pointer to the first element of a dynamically allocated array T and a pointer to any other T

Consider a dummy function that returns the number of elements that the pointer points to.
Let me call it "size".

Sounds good, right?

If not for the fact that all pointers are created equal:

 char* p = new char[10]; size_t ps = size(p+1); // What? char a[10] = {0}; size_t as = size(a); // Hmm... size_t bs = size(a + 1); // Wut? char i = 0; size_t is = size(&i); // OK? 

It can be argued that the first should be 9 , the second 10 , the third 9 and the last 1 , but for this you need to add a "size tag" to each object.
A char will require 128 bits of memory (due to alignment) on a 64 bit machine. This is sixteen times more than necessary.
(Above, a ten-character array a will require at least 168 bytes.)

It may be convenient, but it is also unacceptably expensive.

You could, of course, imagine a version that is only well defined if the argument is really a pointer to the first element of the dynamic allocation by default operator new , but this is not as useful as you might think,

+13
Apr 07 '16 at 9:48
source share

You are right that some part of the system must know something about size. But getting this information is probably not covered by the memory management system API (I think malloc / free ), and the exact size that you requested may not be known, because it may have been rounded.

+3
Apr 07 '16 at 12:22
source share

There is a curious case of operator delete overload, which I found in the form:

 void operator delete[](void *p, size_t size); 

The size parameter defaults to the size (in bytes) of the memory block pointed to by void * p. If so, it’s wise to at least hope that it has the value passed in by calling operator new , and so you just need to divide by sizeof (type) in order to deliver the number of elements stored in the array.

Regarding the “why” part of your question, Martin’s “don’t pay for what you don’t need” rule seems the most logical.

+2
Apr 07 '16 at 9:38 on
source share

It is impossible to find out how you are going to use this array. The selection size does not necessarily correspond to the element number, so you cannot just use the distribution size (even if it is available).

This is a profound error in other languages, not C ++. You achieve the desired functions with std :: vector, but still retain raw access to arrays. Maintaining this raw access is critical for any code that actually needs to do some work.

You will perform operations on subsets of the array many times, and when you have additional accounting built into the language, you must redistribute the subarrays and copy the data to manipulate them using the API, which expects a managed array.

Just consider the trivial case of sorting data items. If you manipulate arrays, you cannot use recursion without copying data to create recursive recursive recursions to create new gifts.

Another example is FFT, which recursively manipulates data starting from 2x2 butterflies and returns back to the entire array.

To fix a managed array, you now need “something else” to fix this defect, and that “something else” is called “iterators”. (Now you control arrays, but almost never pass them to any functions, because you need iterators + 90% of the time.)

+1
Apr 7 '16 at 18:18
source share

The size of the array allocated with new[] is not explicitly saved anywhere, so you cannot access it. And the new[] operator does not return an array, but only a pointer to the first element of the array. If you want to know the size of a dynamic array, you must save it manually or use classes from libraries such as std::vector

-2
Apr 07 '16 at 8:57
source share



All Articles