adding element to an array - c++

How can I add an element to an array where the size of the array is unknown and vectors are prohibited?

If the size of the array is unknown how do you know where to put the element and whether it will fit?
Anyway, if it won't fit you have to allocate a new array that is big enough.
If you allocated originally with malloc rather than new[] you can use realloc. You might be surprised to know that malloc / realloc are not "replaced" by new but are used for a different purpose, and in this case it is a useful thing to use. You can then insert objects into the allocated memory using placement new, and vector works this way. (allocator is used to actually allocate the memory but has an interface like malloc and although the implementation is up to the library author, they will almost certainly use malloc).
If you reallocated using realloc, you need to know that:
Any memory will be copied over. Beware though that if they are non-POD objects stored it is not safe to just do byte-by-byte copy
If realloc fails it returns NULL and your previous array is not freed. Be certain to keep a pointer to the old location until you know realloc worked.
If your array is not POD you cannot realloc, so malloc the new memory and use placement-new with a copy-constructor, then call the destructor on each object of the old memory before freeing it.
Placement new is used so you can allocate more memory than you need for now, i.e. more than you have objects for. This prevents you having to go through this process every single time you append.
I have explained how you might implement vector, but this is probably far too complex for you and probably for your tutor too. So just create an array with new[] and copy over the elements although it is horribly inefficient if you have to do this every time you add one.

You use lists for this purpose. An array is not supposed to be extended.

Your question does not make sense. If you can't use vector, means this is an assignment. I assume you have to use native arrays. If you don't know the size, you just cannot add an element to it. If you knew the size, you would have to allocate a bigger array, copy the contents of the old array plus the new element. Which the vector actually does for you :)

Without knowing the current size of the array and the capacity of the array (the distinction there is important), adding elements to the array is dangerous. You will never know when you have passed the bounds of the array (at least not before your program crashes from a buffer overrun error).
If your professor has banned vector for an assignment, chances are he wants to show you how to manage memory. He's looking for you to create an array using new and properly recognize when you need to allocate a new array of a larger size, copy the original elements, and deallocate the original array using delete.
One hint most professors fail to mention: when you allocate an array using new [], you must also deallocate it using delete [].

Related

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.

Is it possible to partially de-allocate memory from the middle of some object and "split" it?

For example I have an array of 200 integers. What I want to do is convert it to two arrays of 80 integers, removing the 40 integers in between. The goal of course is to use the existing memory block without allocating two new arrays of length 80 integers and copying from the first array, what I want is to cut the initial array from 80 to 120 and treat what is left as two separate arrays.
Move semantics uses a similar low level approach to avoid unnecessary copy of rvalues, so my question is if there is a low level approach to achieve a similar effect but assign the already existing data to multiple objects.
For example assigning pointers to the raw memory addresses of where the cuts are and the new elements begin, forcing them to act as arrays which use the same data, already allocated and filled in by the initial array?
Naturally, I could also delete the initial array and get its address and use that to assign its memory area to a new element, but is it possible to tell C++ on which exact address to allocate a new object? And also, is there a way to guarantee the data of the initial array wont be corrupted in between its deletion and the reallocation of that same memory area to a new object?
Such an approach is absent from any of the books on c++ I've read, but I get the feeling there might very well be some low level trickery to achieve the desired result.
Yes, this is possible using placement-new. However, there is no way to guarantee that the content of a memory-location will not be changed between delete and a reallocation. Anyway, placement-new only enables you to construct an object in memory that you already own. So you'd have to allocate a pool of memory and then do your own memory management inside that pool.
You can use placement new but it's generally not a good idea to go this low-level, unless you are really constrained.
Using it is a good idea when:
You implement a memory pool
You need to write to a precise memory location because the platform requires that (for example, memory mapped I/O on some embedded device).
Disadvantages of using it:
You need to make sure that the allocated memory is large enough to hold the object.
You need to explicitly call the destructor when the object is not needed anymore.
is there a way to guarantee the data of the initial array wont be corrupted in between its deletion and the reallocation of that same memory area to a new object
No, that's up to the OS. It might be possible with a platform-specific API if it exists.
What I'd simply do is pass pointers to the relevant slices:
void i_need_80(int arr[80]); // same as "int*"
std::array<int, 200> the_array;
i_need_80(the_array);
i_need_80(the_array + 120);
In place of std::array<int, 200> you can also have a dynamic std::vector<int> v, in which case you'd say v.data() and v.data() + 120.
Don't use new.
The only thing you can do is call realloc() to resize (and possibly move) a block allocated with malloc() of realloc(). If the block was allocated using new[], even that isn't possible. The things you want require a rewrite (re-invention) of the memory management functions malloc(), free() and realloc().

C++ Deleting part of dynamic array

Say I have a dynamic array like:
int* integers = new int[100];
Is there a way to delete only part of the array such as:
int* integers2 = integers + 50;
delete[] integers2;
I want to not only delete everything 50 and beyond, but if I call another delete[] on the original integers array, then it would only delete the correct amount of memory and not try to delete the originally allocated amount and seg fault.
Why I want to do this: I have a data structure that is structured in levels of arrays, and I want to be able to create this data structure from a full array. So I want to be able to say
int* level1 = integers;
int* level2 = integers + 50;
int* level3 = integers + 100;
But when level 3 is no longer needed, the data structure will automatically delete[] level3. I need to know that this will behave correctly and not just destroy everything in the array. If it will then I need to just create new arrays and copy the contents over, but it would be nice to avoid doing that for performance reasons.
Edit: Everyone seems to be jumping to the conclusion that I just should use a dynamic resizing container (ie vector, deque) in the first place for my data structure. I am using levels of arrays for a good reason (and they aren't equally sized like I make it look like in my example). I was merely looking for a good way to have a constructor to my data structure that takes in an array or vector and not need to copy the original contents over into the new data structure.
No, this will not behave correctly. You can only delete[] pointers that you got from new[], else the results are undefined and bad things might happen.
If you really need the array to get smaller you have to allocate a new one and copy the contents manually.
Typically when memory gets allocated, there is some housekeeping stuff before the pointer.
i.e. houskeeping (pointer) data
You will mess that up.
int* integers2 = integers + 50;
delete[] integers2;
Will not work because new is created on int*, so space of 100 int has been assigned to integers, now integers2 is only a pointer to 50th location of integers, it has no space assigned to it of its own, so using delete will not delete rest of integers2, it'll only give erratic results.
What you can do is copy the first 50 in another array, and delete the previous array completely.
delete will only delete the pointer which has space assigned to it, using delete to another pointer pointing to the space assigned to first pointer will not delete any space assigned to the first pointer.
delete[] integers2 will not delete any space assigned to integers1 or any other pointer.
Dynamic allocators (like new) generally don't like you releasing part of the memory they gave you. If you use the <malloc.h> defined library functions malloc() and free() instead of new and delete, then you can use realloc(), though in most cases that you would care about the size difference it's just going to copy for you anyway.
Dynamically sizing containers generally use an exponential rule for resizing: if you run out of space, they (for example) double the allocation (and copy the old data over), if you remove data until you are using (for example) less than half the allocation they copy into a smaller allocation. This means you never waste more than half the memory, and the cost of copying per element added or removed is effectively constant. Implementing all of this is a pain in the ass, though, so just use std::vector and let it do it for you :).
No you can't do this with a fixed sized array allocated with new[]. If you want to have a dynamic array use one of the STL containers, such as std::vector.

If pointers can dynamically change the size of arrays at run time, why is it necessary to initialize the array with a size?

For instance:
int* pArray;
pArray = new array[];
instead of:
int* pArray;
pArray = new array[someNumber];
Since pointers are able to dynamically change the size of an array at run time, and the name of the pointer points to the first element of an array, shouldn't the default size be [1]? Does anyone know what's happening behind the scene?
Since pointers are able to dynamically change the size of an array at run time
This is not true. They can't change the size unless you allocate a new array with the new size.
If you want to have an array-like object that dynamically changes the size you should use the std::vector.
#include<vector>
#include<iostream>
...
std::vector<int> array;
array.push_back(1);
array.push_back(2);
array.push_back(3);
array.push_back(4);
std::cout << array.size() << std::endl; // should be 4
When you create an array with new, you are allocating a specific amount of memory for that array. You need to tell it how many items are to be stored so it can allocate enough memory.
When you "resize" the array, you are creating a new array (one with even more memory) and copying the items over before deleting the old array (or else you have a memory leak).
Quite simply, C++ arrays have no facility to change their size automatically. Therefore, when allocating an array you must specify it size.
Pointers cannot change an array. They can be made to point to different arrays at runtime, though.
However, I suggest you stay away from anything involving new until you have learned more about the language. For arrays changing their size dynamically use std::vector.
Pointers point to dynamically allocated memory. The memory is on the heap rather than the stack. It is dynamic because you can call new and delete on it, adding to it and removing from it at run time (in simple terms). The pointer has nothing to do with that - a pointer can point to anything and in this case, it just happens to point to the beginning of your dynamic memory. The resizing and management of that memory is completely your responsibility (or the responsibility of the container you may use, e.g. std::vector manages dynamic memory and acts as a dynamic array).
They cannot change the size dynamically. You can get the pointer to point to a new allocation of memory from the heap.
Behind the scenes there is memory allocated, a little chunk of silicium somewhere in your machine is now dedicated to the array you just newed.
When you want to "resize" your array, it is only possible to do so in place if the chunk of silicium has some free space around it. Most of the times, it is instead necessary to reserve another, bigger, chunk and copy the data that were in the first... and obviously relinquish the first (otherwise you have a memory leak).
This is done automatically by STL containers (like std::vector or std::deque), but manually when you yourself call new. Therefore, the best solution to avoid leaks is to use the Standard Library instead of trying to emulate it yourself.
int *pArray = new int; can be considered an array of size 1 and it kinda does what you want "by default".
But what if I need an array of 10 elements?
Pointers do not have any magical abilites, they just point to memory, therefore:
pArray[5] = 10; will just yield a run-time error (if you are lucky).
Therefore there is a possibility to allocate an array of needed size by calling new type[size].