Dynamic and static array - c++

I am studying C++ reading Stroustrup's book that in my opinion is not very clear in this topic (arrays). From what I have understood C++ has (like Delphi) two kind of arrays:
Static arrays that are declared like
int test[3] = {10,487,-22};
Dynamic arrays that are called vectors
std::vector<int> a;
a.push_back(10);
a.push_back(487);
a.push_back(-22);
I have already seen answers about this (and there were tons of lines and concepts inside) but they didn't clarify me the concept.
From what I have understood vectors consume more memory but they can change their size (dynamically, in fact). Arrays instead have a fixed size that is given at compile time.
In the chapter Stroustrup said that vectors are safe while arrays aren't, whithout explaining the reason. I trust him indeed, but why? Is the reason safety related to the location of the memory? (heap/stack)
I would like to know why I am using vectors if they are safe.

The reason arrays are unsafe is because of memory leaks.
If you declare a dynamic array
int * arr = new int[size]
and you don't do delete [] arr, then the memory remains uncleared and this is known as a memory leak. It should be noted, ANY time you use the word new in C++, there must be a delete somewhere in there to free that memory. If you use malloc(), then free() should be used.
http://ptolemy.eecs.berkeley.edu/ptolemyclassic/almagest/docs/prog/html/ptlang.doc7.html
It is also very easy to go out of bounds in an array, for example inserting a value in an index larger than its size -1. With a vector, you can push_back() as many elements as you want and the vector will resize automatically. If you have an array of size 15 and you try to say arr[18] = x,
Then you will get a segmentation fault. The program will compile, but will crash when it reaches a statement that puts it out of the array bounds.
In general when you have large code, arrays are used infrequently. Vectors are objectively superior in almost every way, and so using arrays becomes sort of pointless.
EDIT: As Paul McKenzie pointed out in the comments, going out of array bounds does not guarantee a segmentation fault, but rather is undefined behavior and is up to the compiler to determine what happens

Let us take the case of reading numbers from a file.
We don't know how many numbers are in the file.
To declare an array to hold the numbers, we need to know the capacity or quantity, which is unknown. We could pick a number like 64. If the file has more than 64 numbers, we start overwriting the array. If the file has fewer than 64 (like 16), we are wasting memory (by not using 48 slots). What we need is to dynamically adjust the size of the container (array).
To dynamically adjust the capacity of an array, a new larger array must be created, then elements copied and the old array deleted.
The std::vector will adjust its capacity as necessary. It handles the dynamic allocation of memory for you.
Another aspect is the passing of the container to a function. With an array, you need to pass the array and the capacity. With std::vector, you only need to pass the vector. The vector object can be queried about its capacity.

One Security I can see is that you can't access something in vector which is not there.
What I meant by that is , if you push_back only 4 elements and you try to access index 7 , then it will throw back an error. But in array that doesn't happen.
In short, it stops you from accessing corrupt data.
edit :
programmer has to compare the index with vector.size() to throw an error. and it doesn't happne automatically. One has to do it by himself/herself.

Related

C++ doesn't tell you the size of a dynamic array. But why?

I know that there is no way in C++ to obtain the size of a dynamically created array, such as:
int* a;
a = new int[n];
What I would like to know is: Why? Did people just forget this in the specification of C++, or is there a technical reason for this?
Isn't the information stored somewhere? After all, the command
delete[] a;
seems to know how much memory it has to release, so it seems to me that delete[] has some way of knowing the size of a.
It's a follow on from the fundamental rule of "don't pay for what you don't need". In your example delete[] a; doesn't need to know the size of the array, because int doesn't have a destructor. If you had written:
std::string* a;
a = new std::string[n];
...
delete [] a;
Then the delete has to call destructors (and needs to know how many to call) - in which case the new has to save that count. However, given it doesn't need to be saved on all occasions, Bjarne decided not to give access to it.
(In hindsight, I think this was a mistake ...)
Even with int of course, something has to know about the size of the allocated memory, but:
Many allocators round up the size to some convenient multiple (say 64 bytes) for alignment and convenience reasons. The allocator knows that a block is 64 bytes long - but it doesn't know whether that is because n was 1 ... or 16.
The C++ run-time library may not have access to the size of the allocated block. If for example, new and delete are using malloc and free under the hood, then the C++ library has no way to know the size of a block returned by malloc. (Usually of course, new and malloc are both part of the same library - but not always.)
One fundamental reason is that there is no difference between a pointer to the first element of a dynamically allocated array of T and a pointer to any other T.
Consider a fictitious function that returns the number of elements a pointer points to.
Let's call it "size".
Sounds really nice, right?
If it weren't 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?
You could argue that the first should be 9, the second 10, the third 9, and the last 1, but to accomplish this you need to add a "size tag" on every single object.
A char will require 128 bits of storage (because of alignment) on a 64-bit machine. This is sixteen times more than what is necessary.
(Above, the ten-character array a would require at least 168 bytes.)
This may be convenient, but it's also unacceptably expensive.
You could of course envision a version that is only well-defined if the argument really is a pointer to the first element of a dynamic allocation by the default operator new, but this isn't nearly as useful as one might think.
You are right that some part of the system will have to know something about the size. But getting that information is probably not covered by the API of memory management system (think malloc/free), and the exact size that you requested may not be known, because it may have been rounded up.
You will often find that memory managers will only allocate space in a certain multiple, 64 bytes for example.
So, you may ask for new int[4], i.e. 16 bytes, but the memory manager will allocate 64 bytes for your request. To free this memory it doesn't need to know how much memory you asked for, only that it has allocated you one block of 64 bytes.
The next question may be, can it not store the requested size? This is an added overhead which not everybody is prepared to pay for. An Arduino Uno for example only has 2k of RAM, and in that context 4 bytes for each allocation suddenly becomes significant.
If you need that functionality then you have std::vector (or equivalent), or you have higher-level languages. C/C++ was designed to enable you to work with as little overhead as you choose to make use of, this being one example.
There is a curious case of overloading the operator delete that I found in the form of:
void operator delete[](void *p, size_t size);
The parameter size seems to default to the size (in bytes) of the block of memory to which void *p points. If this is true, it is reasonable to at least hope that it has a value passed by the invocation of operator new and, therefore, would merely need to be divided by sizeof(type) to deliver the number of elements stored in the array.
As for the "why" part of your question, Martin's rule of "don't pay for what you don't need" seems the most logical.
There's no way to know how you are going to use that array.
The allocation size does not necessarily match the element number so you cannot just use the allocation size (even if it was available).
This is a deep flaw in other languages not in C++.
You achieve the functionality you desire with std::vector yet still retain raw access to arrays. Retaining that raw access is critical for any code that actually has to do some work.
Many times you will perform operations on subsets of the array and when you have extra book-keeping built into the language you have to reallocate the sub-arrays and copy the data out to manipulate them with an API that expects a managed array.
Just consider the trite case of sorting the data elements.
If you have managed arrays then you can't use recursion without copying data to create new sub-arrays to pass recursively.
Another example is an FFT which recursively manipulates the data starting with 2x2 "butterflies" and works its way back to the whole array.
To fix the managed array you now need "something else" to patch over this defect and that "something else" is called 'iterators'. (You now have managed arrays but almost never pass them to any functions because you need iterators +90% of the time.)
The size of an array allocated with new[] is not visibly stored anywhere, so you can't access it. And new[] operator doesn't return an array, just a pointer to the array's first element. If you want to know the size of a dynamic array, you must store it manually or use classes from libraries such as std::vector

Is dynamic memory deletion also possible in arrays?

Supposingly I've declared a character array and take a string from the user as follows:
char s[100000];
std::cin>>s;
Now say the user has entered the string "Program". My character array will be as as follows:
'P''r''o''g''r''a''m''\0'......(99992 remaining indices with no/junk values)
Is there a way to free the space occupied those 99992 indices? Similarly if I've an integer array of size say 100000 and I'm using only first 10 indices during run time, is there a way to resize my array during the run time of my program. I know we can use vectors for this purpose but is the thing possible somehow using arrays? For integer arrays, I know we may declare arrays dynamically and then declare size as per our requirement but say I have array of 10 integers as follows:
1 2 3 4 5 6 7 8 9 10
Now, I want to use only first 9 indices and wnat to kind of delete the 10th index. In other words, along with dynamic allocation, is dynamic deletion also possible with arrays?
EDIT:
I know the thing is possible using STLs but I want to know if we can do the same thing in arrays?
No.
If you have arrays defined with a fixed size, you cannot release part of those arrays at run-time. Use a dynamically allocated array of some sort — probably a string or vector<int> for your two example arrays respectively, though a vector<char> might also work sufficiently well for you.
When you write:
char s[100000];
You are telling the compiler to stack 100000 bytes in the program stack.
However when you reserve memory dynamically:
char * = new char[100000];
You are asking the system to reserve 100000 bytes in the heap so you can handle that asked memory as you want, even tell the system to free it as a resource.
You can't free memory at the stack until your local context is finished. For example, exiting the function you where you declared char s[100000].
Check this question:
What and where are the stack and heap?
std::string is implemented using dynamic memory allocation at the heap and that is why it allows you to reduce its size.
that is not possible.
you may wrap your user input capturing in a subroutine that allocates stack space and allocates heap memory at the actual required length.
You are confused over when to use static allocation and when to use dynamic allocation.
Static allocation is used when the maximum number of items is known in advance, at compile-time.
Dynamic allocation is used when the number of items is unknown until run-time.
There exists no other case than the two above. You cannot mix them and it wouldn't make sense to do so.
The only case where you should allocate a static array char s[100000]; is the case where you know, at some point, that there will be 100000 items that the program needs to handle.
You designed your program to handle the worst case of 100000 items. It must still be able to handle that many. If the program needs to have an array of variable, unknown size, you should have used dynamic allocation.
If we ignore that C++ exists, then what you would have done in C is this:
char* s = malloc(sizeof(*s) * 100000);
...
s = realloc(s, some_strlenght);
Please note that huge static arrays allocated on the stack is bad practice in many operative systems. So you might have to declare the 100000 array on the heap anyway, even though you won't resize it. Simply because there is likely not enough stack space in your process to declare large, bulky variables like that.
(Also, because of the way C++ is designed, std::string and std::vector etc are always implemented with dynamic memory internally, even if you only use them with one fixed size.)

C++ dynamic array without STL

This is part of an assignment however I just asking for clarification:
Load data from ATM.txt and store them in a dynamic array (ATM type,
not STL) when the program starts up.
How exactly do I do dynamic arrays without STL? I thought perhaps the assignment means using pointers, the "ATM Type" threw me off.
It's mentioned again:
file accounts.txt into a dynamic array (Account type, not STL)
--not part of Assignment
I've never understood the use of memory unsafe operations, eg pulling the number of items in a file from the first line:
eg.
5
abc
def
hij
kml
mno
Wouldn't it be smarter to use STL (vectors, or C++11 arrays) and not rely on the number in the file as it may not be accurate causing buffer overflows etc?
//Edit
Define a class Account in a file Account.h which contains the data members: customer
id, BSB number, etc.
I assume Account and ATM types are those classes.
The most basic form of dynamic array is one created using new[], and destroyed using delete[]:
ATM * atms = new ATM[count];
// do stuff with the array
delete [] atms;
However, this brings the danger that the code using the array might throw an exception, return from the function, or otherwise prevent the delete[] from happening. If that happens, then you will lose the only pointer to the allocated memory, and it will remain allocated but inaccessible; this is known as a memory leak. For this reason, it's better to wrap the array in a class, with:
member variables to store a pointer to the array, and (optionally) its size
constructors and/or functions to allocate the array
a destructor to delete the array
(optionally) function(s) to resize the array
Deleting the allocation in an object's destructor uses the principle of RAII to ensure that the array is deleted once it is no longer needed.
This leaves one more danger: if you copy this array object, then you will end up with two objects that both try to delete the same array, which is disasterous. To prevent this, you'll need to consider the Rule of Three. Either write a copy constructor and copy-assignment operator to allocate a new array and copy the contents; or delete them. (If you're learning old-fashioned C++, then you can't delete member functions, so you'll have to declare them private and not implement them instead).
Wouldn't it be smarter to use STL?
Usually, yes. But if you're learning C++, it's a good idea to understand how memory management works, as well as how to get the library to handle it for you. That's probably part of the point of this exercise.
A common approach for this kind of assignment would be to simulate the auto-expanding behavior of a vector on your own. Allocate an array for your data on the heap, and keep track of its length and the number of items you've stored in the array.
Once you've filled the array with your data, expand the maximum size by some amount and allocate a new array. This allows you to copy the data from the old array into the new array, and then continue adding items until you run out of space again.
Basically if you need to implement a dynamic array without using STL, you have to deal explicitely with memory allocation/deallocation.
Basically you have to:
Allocate space with malloc the first time array is constructed or used
Keep track of inserted/removed elements
Use realloc when you have finished the allocated space
Free the allocated space when the array is destroyed
Of course implementing a good STL like container like std::vector isn't an easy task (eventually a nice homework!).
What I can suggest is the following:
Avoid as much as possible reallocation. When the space is finished, allocate some more space in order to avoid to continuosly call realloc (see std::vector::reserve)
Avoid to realloc space when elements are removed. Once you have allocated, unless memory usage is too high, let the allocated space as is, in order to avoid future reallocation.
Wouldn't it be smarter to use STL (vectors, or C++11 arrays) and not
rely on the number in the file as it may not be accurate causing
buffer overflows etc?
The internals of std::vector aren't magic. It's possible to manually do yourself what std::vector does for you.
It sounds like that's what you're supposed to do for this assignment; make your own 'ATM type' that can manage reading data safely from the ATM.txt file, and an 'Account type' that can hold data from the accounts.txt file. You should probably get some clarification from whomever wrote the assignment on how exactly they expect these types to be designed/used. Also looking back at whatever class materials you have should tell you what you need to know in terms of using dynamic arrays.
Since this is homework we don't want to give answers directly, but in general what I suggest is:
Make a class myDynamicArray
Make the class contain an int or long to store array size
Allocate memory for your array using "new". From the assignment, it looks like it might be an array of strings or, if the professor is strictly banning STL (string is now considered STL), it will be an array of character arrays.
Write an insert method which, before inserting, checks the size (see #2) of your array and, if it isn't large enough, makes it bigger. One way to do this without using pre-C++ functions, which I assume is best since this is a C++ class, is to allocate a new array of larger size --> copy data from old array --> Insert any new data. How much larger? You might pick, say, 20% larger with each new allocation. Microsoft's C# allocates "the next largest prime number" of elements, though they have really fast memory allocation routines.
Don't forget to delete() the dynamic array when finished with it (what "finished" means depends on the assignment). Note that once the program exits, technically the memory should be freed up automatically, but it's very bad practice to not free it up yourself (think larger, non-academic programs that aren't regularly shut down).
I'd avoid the template code another user provided. I'm sure it's great code, but it's going to raise an eyebrow to use something that advanced in an early C++ class.
Suggested reading:
http://www.cplusplus.com/doc/tutorial/dynamic/

Dynamic arrays vs STL vectors exact difference?

What is the exact difference between dynamic arrays and vectors. It was an interview question to me.
I said both have sequential memory.
Vectors can be grown in size at any point in the code. He then said even dynamic arrays can be grown in size after creating.
I said vectors are error free since it is in the standard library. He said he will provide as .so file of dynamic arrays which is error free and has all the qualities on par with STL.
I am confused and didn't answer the exact difference. When I searched on Internet, I had seen the above statements only.
Can someone please explain me the exact difference? And what was the interviewer expecting from me?
He said he will provide as .so file of dynamic arrays which is error free and has all the qualities on par with STL.
If his dynamic array class does the same as std::vector (that is: it implements RAII to clean up after itself, can grow and shrink and whatever else std::vector does), then there's only one major advantage std::vector has over his dynamic array class:
std::vector is standardized and everybody knows it. If I see a std::vector in some piece of code, I know exactly what it does and how it is supposed to be used. If, however, I see a my::dynamic_array, I do not know that at all. I would need to have to look at its documentation or even — gasp! — implementation to find out whether my_dynamic_array::resize() does the same as std::vector::resize().
A great deal here depends on what he means by a "dynamic array". Most people mean something where the memory is allocated with array-new and freed with array-delete. If that's the intent here, then having qualities on a par with std::vector simply isn't possible.
The reason is fairly simple: std::vector routinely allocates a chunk of memory larger than necessary to hold the number of elements currently being stored. It then constructs objects in that memory as needed to expand. With array-new, however, you have no choice -- you're allocating an array of objects, so if you allocate space for (say) 100 objects, you end up with 100 objects being created in that space (immediately). It simply has no provision for having a buffer some part of which contains real objects, and another part of which is just plain memory, containing nothing.
I suppose if yo want to stretch a point, it's possible to imitate std::vector and still allocate the space with array-new. To do it, you just have to allocate an array of char, and then use placement new to create objects in that raw memory space. This allows pretty much the same things as std::vector, because it is nearly the same thing as std::vector. We're still missing a (potential) level of indirection though -- std::vector actually allocates memory via an Allocator object so you can change exactly how it allocates its raw memory (by default it uses std::allocator<T>, which uses operator new, but if you wanted to, you could actually write an allocator that would use new char[size], though I can't quite imagine why you would).
You could, of course, write your dynamic array to use an allocator object as well. At that point, for all practical purposes you've just reinvented std::vector under a (presumably) new name. In that case, #sbi is still right: the mere fact that it's not standardized means it's still missing one of the chief qualities of std:::vector -- the quality of being standardized and already known by everybody who knows C++. Even without that, though, we have to stretch the phrase "dynamic array" to (and I'd posit, beyond) the breaking point to get the same qualities as std::vector, even if we ignore standardization.
I expect they wanted you to talk about the traps of forgetting to delete the dynamic array with operator delete[] and then got confused themselves when they tried to help you along; it doesn't make much sense to implement a dynamic array as a plain class since it bakes in the element type.
The array memory allocated for vectors is released when the vector goes out of scope, in case the vector is declared on the stack (the backing array will be on the heap).
void foo() {
vector<int> v;
// ... method body
// backing array will be freed here
}
It says here: "Internally, vectors use a dynamically allocated array to store their elements."
Underlying concept of vectors is dynamically allocated array.
http://www.cplusplus.com/reference/vector/vector/
Maybe it's that dynamic array you would go through the copy process to a new dynamic array whenever you want to resize, but you are able to control when it does that depending on your knowledge of the data going into the array.
Whereas a vector uses the same process, but a vector does not know if it will grow or not later, so it probably allocates extra storage for possible growth in size, therefore it COULD possibly consume more memory space than intended to manage itself compared to dynamic arrays.
So, I'd say the difference is to use a vector when managing it's size is not a big deal, where you would use a dynamic array when you would rather do the resizing yourself.
Arrays have to be deallocated explicitly if defined dynamically whereas vectors are automatically de-allocated from heap memory.
Size of array cannot be determined if dynamically allocated whereas Size of the vector can be determined in O(1) time.
3.When arrays are passed to a function, a separate parameter for size is also passed whereas in case of passing a vector to a function, there is no such need as vector maintains variables which keeps track of size of container at all times.
4.When we allocate array dynamically then after size is initialized we cannot change the size whereasin vector we can do it.

Why "delete [][]... multiDimensionalArray;" operator in C++ does not exist

I was always wondering if there is operator for deleting multi dimensional arrays in the standard C++ language.
If we have created a pointer to a single dimensional array
int *array = new int[size];
the delete looks like:
delete [] array;
That's great. But if we have two dimension array, we can not do
delete [][] twoDimenstionalArray;
Instead, we should loop and delete the items, like in this example.
Can anybody explain why?
Technically, there aren't two dimensional arrays in C++. What you're using as a two dimensional array is a one dimensional array with each element being a one dimensional array. Since it doesn't technically exist, C++ can't delete it.
Because there is no way to call
int **array = new int[dim1][dim2];
All news/deletes must be balanced, so there's no point to a delete [][] operator.
new int[dim1][dim2] returns a pointer to an array of size dim1 of type int[dim2]. So dim2 must be a compile time constant. This is similar to allocating multi-dimensional arrays on the stack.
The reason delete is called multiple times in that example is because new is called multiple times too. Delete must be called for each new.
For example if I allocate 1,000,000 bytes of memory I cannot later delete the entries from 200,000 - 300,00, it was allocated as one whole chunk and must be freed as one whole chunk.
The reason you have to loop, like in the example you mention, is that the number of arrays that needs to be deleted is not known to the compiler / allocator.
When you allocated your two-dimensional array, you really created N one-dimensional arrays. Now each of those have to be deleted, but the system does not know how many of them there are. The size of the top-level array, i.e. the array of pointers to your second-level arrays, is just like any other array in C: its size is not stored by the system.
Therefore, there is no way to implement delete [][] as you describe (without changing the language significantly).
not sure of the exact reason from a language design perspective, I' guessing it has something to do with that fact that when allocating memory you are creating an array of arrays and each one needs to be deleted.
int ** mArr = new int*[10];
for(int i=0;i<10;i++)
{
mArr[i]=new int[10];
}
my c++ is rusty, I'm not sure if thats syntactically correct, but I think its close.
While all these answers are relevant, I will try to explain what came to an expectation, that something like delete[][] array; may work on dynamically allocated arrays and why it's not possible:
The syntax int array[ROWS][COLS]; allowed on statically allocated arrays is just abstraction for programmers, which in reality creates one-dimensional array int array[ROWS*COLS];. But during compilation process (when dimension sizes COLS and ROWS must be constants by standard) the compiler also remembers the size of those dimensions, that are necessary to later address elements using syntax e.g. array[x][y] = 45. Compiler, being known of this size, will then replace [x][y] with the corresponding index to one-dimensional array using simple math: [COLS*x + y].
On the other hand, this is not the case with dynamically allocated arrays, if you want the same multi-dimensional functionality (in fact notation). As their size can be determined during runtime, they would have to remember the size of each additional dimension for later usage as well - and remember that for the whole life of the array. Moreover, system changes would have to be implemented here to work with arrays actually as multi-dimensional, leaving the form of [x][y] access notation in the code, not replacing it with an one-dimensional notation during compilation, but later replacing it within runtime.
Therefore an absence of array = new int[ROWS][COLS] implies no necessity for delete[][] array;. And as already mentioned, it can't be used on your example to delete your "multi-dimensional" array, because your sub-arrays (additional dimensions) are allocated separately (using separate new call), so they are independent of the top array (array_2D) which contains them and they all can't be deleted at once.
delete[] applies to any non-scalar (array).
You can use a wrapper class to do all those things for you.
Working with "primitive" data types usually is not a good solution (the arrays should be encapsulated in a class). For example std::vector is a very good example that does this.
Delete should be called exactly how many times new is called. Because you cannot call "a = new X[a][b]" you cannot also call "delete [][]a".
Technically it's a good design decision preventing the appearance of weird initialization of an entire n-dimensional matrix.
Well, I think it is easy to implement, but too dangerous. It is easy to tell whether a pointer is created by new[], but hard to tell about new[]...[](if allowed).