As Cheers and hth said in the comments, the best way is to use std::vector
, it takes care of the memory management itself.
- How to declare dynamic memory allocation of an array without prior knowledge of the size?
The idea is, you do not allocate any memory if you do not know the size, and when adding elements to it, you can increase the memory, see example below.
Implementing a class that works like std::vector
:
vector
uses two sizes, one is the size
which is the number of elements your vector
is currently holding, capacity
is the number of elements which your vector
can hold (memory is allocated for capacity
)
Pre-requisites: I'm assuming that you know the basic memory allocation and de-allocation, that you can allocate memory using new
operator, and de-allocate using delete
operator.
Note: I'm implementing some methods for MyIntVector
that uses only int
array for simplicity, but you can always implement a templated class.
Implementation:
You can provide a default constructor for your class, which doesn't allocate any memory, sets the size
and capacity
to 0
(client programs can use this constructor, if the size is not known).
You can also provide a constructor which takes a size
that will be used as the starting size
, when creating the MyIntVector
Also provide a destructor to completely de-allocate the allocated memory.
class MyIntVector{
size_t _size;
size_t _capacity;
int* _data;
public:
MyIntVector(){
_size = 0;
_capacity = 0;
_data = nullptr;
}
MyIntVector(size_t size){
_size = size;
_capacity = size;
_data = new int[_capacity];
}
~MyIntVector(){
if (_data){
delete[] _data;
}
_data = nullptr;
_size = _capacity = 0;
}
};
Now, if you want to add some element to your MyIntVector
, you can implement a push_back
function, like std::vector
does.
class MyIntVector{
//...
void push_back(int elem){
if (_size >= _capacity){
// Oops, we're out of memory, let's make room for this elem first
resize(_capacity > 0? _capcity * 2 : 10);
}
// Now, there's enough memory to hold this elem
_size++;
_data[_size - 1] = elem;
}
void resize(size_t newCapacity){
if (newCapacity != _capacity){
if (_size == 0){
_capacity = newCapacity;
_data = new int[_capacity];
}
else {
// create a temporary array to hold the elements of _data
int* temp = new int[_size];
for (size_t i = 0; i < _size; i++)
temp[i] = _data[i];
// de-allocate the memory of _data
delete[] _data;
// allocate memory in _data with newCapacity
_capacity = newCapacity;
_data = new int[_capacity];
// copy the elements of temporary array back in _data
for (size_t i = 0; i < _size; i++){
_data[i] = temp[i];
}
// done with the temporary array, de-allocate it.
delete[] temp;
temp = nullptr;
}
}
}
//...
};
push_back
function:
The push_back
function, that I've implemented in above example, it sees whether the new element can be added to the MyIntVector
without any need to allocate any new memory or not, if not, it just increases the _size
by 1
and copies the element. If there's a need for new memory, it calls the resize
method with doubled capacity (in case, there's already some allocated memory there.) or some hard-coded value, say 10
(in case, where there's not any previously allocated memory)
resize
function:
The resize
function takes a newCapacity
as argument, and allocates the required memory in _data
, mainly it creates a temporary array to hold the elements of _data
and then de-allocates the memory in _data
, allocates a larger memory in _data
, copies back the from temp
to _data
and de-allocates the temp
array.
Note: This implementation of resize
should only be used when increasing the _capacity
, it should not be called for decreasing the _capacity
So, the idea is, that you can increase the size of the array, by using a temporary array for holding the elements, de-allocating the previous array, allocating a new array, and copying back the elements from temporary array. You can implement different methods that std::vector
provides for your exercise.
If you don't want to de-allocate and re-allocate the memory every time you increase the capacity, you can always implement a Linked List, here's a tutorial for implementing a Linked List, but there's a drawback of Linked List, that you can't randomly access elements from the Linked List like you can from an array.
- Suppose I use a variable to dynamically allocate memory to the array but later on in the program the size of array is reduced.Will there be automatic de-allocation of memory?
There's no automatic de-allocation of memory, you'll have to manually decrease the _capacity
if you want.
You can add a pop_back
method in your MyIntVector
class to remove an element.
class MyIntVector{
// ...
int pop_back(){
if (_size == 0){
// You can throw some exception here if you want.
throw exception("No elements found");
}
_size--;
return _data[_size];
}
// ...
};
You can manually decrease the _capacity
before returning the element.
You can also provide an implementation of subscript operator []
for your MyIntVector
class to provide random access in the array.