1

I am learning the dynamic memory allocation process in c++.

1.How to declare dynamic memory allocation of an array without prior knowledge of the size?

2.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?

If not then how to update it?

Please spare me if these are silly questions.If you answer please include an example program.

  • 21
    Just use `std::vector`. It takes care of the memory management. – Cheers and hth. - Alf Sep 14 '16 at 17:06
  • 3
    As the programmer, when you use dynamically allocated memory, you have to do all of the memory management. I.e. allocation, keeping track of it, and deallocation. This includes resizing (creating a new different sized array and copying the elements over to the new one) it when you think is necessary. This is a lot of work, so I'd suggest using the c++ standard containers (`std::vector`). – Timothy Murphy Sep 14 '16 at 17:09
  • 1
    You might want to read about the rule of zero. https://accu.org/index.php/journals/1896 It touches on the complexity of resource management. – Captain Giraffe Sep 14 '16 at 17:12
  • This is too broad, what research have you done? – Fantastic Mr Fox Sep 14 '16 at 17:25
  • 2
    Just a note: remember `std::unique_ptr` and `std::shared_ptr` (and `std::make_unique`/`std::make_shared`) exist. Don't use manual memory management with raw pointers in modern C++ (except *very* rarely and for *extremely* good reasons (which you won't know as a new learner)). – Jesper Juhl Sep 14 '16 at 17:28

3 Answers3

0

If you do choose to dynamically allocate memory, you will need to use the operator new[] for an array, which is considered a different operator in c++ than new for non-array types.

1) Here is an example of how to dynamically allocate an array:

int length = 10;
int *myArray = new int[length];

// do something
myArray[0] = 42;

When you are done, you will need to release the memory with delete[]:

delete[] myArray;

2) No, there is no automatic de-allocation of dynamically allocated memory in C++ unless you are using smart pointers (What is a smart pointer and when should I use one?).

If you want to resize your array, you will have to do it manually:

delete[] myArray;

int newLength = 5;
myArray = new int[newLength];
Community
  • 1
  • 1
frameworks
  • 11
  • 4
0

As @frameworks pointed out, you will need the operator new[] to allocate memory for an array and you need to call delete[] to free that memory. If there is no delete[] for a new[], your program will leak memory. (If there is more than one delete[] called for a single new[], your program will segfault / crash.)

However, it is not always trivial to ensure that memory allocated with new[] (or new) gets always cleaned up by a corresponding delete[] (or delete), and only gets cleaned up once. That is especially true for code with complex control flow, code where pointers get passed around or situations where exceptions can be thrown between new[] and delete[].

In other words: Wherever there is a new, there probably is a leak.

So to save you all that trouble of manual memory management, use std::vector instead. This container takes care of the memory management for you.

Whenever you are tempted to write something like

int *myArray = new int[3];
//do something with myArray
delete[] myArray;

you should write

std::vector<int> myArray;
//do something with myArray

instead. You do not need a delete here and methods like std::vector::push_back() take care of the required size adjustments for the underlying structure, should it not provide enough space to accomodate all pushed values. You can also use std::vector::shrink_to_fit() to remove unused elements. (However, shrink_to_fit is a non-binding request to reduce the internal size. That is, results may vary between compilers.)

Striezel
  • 3,693
  • 7
  • 23
  • 37
0

As Cheers and hth said in the comments, the best way is to use std::vector, it takes care of the memory management itself.


  1. 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.


  1. 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.

Ahmad Khan
  • 2,655
  • 19
  • 25