kabugh
kabugh

Reputation: 315

How to dynamically allocate and deallocate a 2D array using pointers in c++?

I'd like to dynamically allocate and then deallocate a 2D array using pointers. My idea is to create a pointer to an array of pointers, where each pointer points to an int and that's how I would like to do it. The functions are type of bool as I want to return a boolean whether the action was successful or not.

The problem is that deallocateTwoDimTable function doesn't return a bool, so it seems like it doesn't work at all. If I don't use int** table = nullptr; but leave it uninitialised int** table, then I get the error (when deallocating) that the memory that I want to free haven't been initialised.

The code does work if I change the parameter int **table to int **&table, but I guess that means passing by reference instead of using pointers. How do I make it work? All the help is really appreciated :)

Here's my main method:

int main() {
    int** table = nullptr;
        
    int sizeX = 5; // rows
    int sizeY = 3; // columns
    
    bool allocationResult = allocateTwoDimTable(table, sizeX, sizeY);
    cout << endl << "allocation result: " << (allocationResult ? "true" : "false") << endl;
    
    bool deallocationResult = deallocateTwoDimTable(table, sizeX);
    cout << endl << "deallocation result: " << (deallocationResult ? "true" : "false");
}

Allocation function:

bool allocateTwoDimTable(int **table, int sizeX, int sizeY) {
    if (sizeX <= 0 || sizeY <= 0) return false;

    // allocate 2D table
    table = new int*[sizeX];
    for(int i = 0; i < sizeX; i++) {
        table[i] = new int[sizeY];
    }

    cout << endl << "Table " << sizeX << " x " << sizeY << endl;
    for(int i = 0; i < sizeX; i++) {
        cout << endl;
        for(int j = 0; j < sizeY; j++) {
            cout << table[i][j] << ", ";
        }
    }

    return true;
}

Deallocation function:

bool deallocateTwoDimTable(int **table, int sizeX) {
    if(sizeX <= 0) return false;

    for (int k = 0; k < sizeX; k++) {
        delete[] table[k];
    }

    delete[] table;

    return true;
}

Upvotes: 1

Views: 553

Answers (3)

anastaciu
anastaciu

Reputation: 23802

When you need to pass reference or by pointer, when given the opportunity, it's better to pass by reference.

A pointer can take null arguments, a reference can't, it's safer to use, unless, for some reason, you specifically need to pass null arguments which I believe is not the case.

Note that you're accessing uninitialized memory when you print the array.

Also note that despite using boolean flag to signal allocation errors you're code still is vulnerable, a better way to do this would be to use std::exception.

bool allocateTwoDimTable(int** &table, int sizeX, int sizeY) {
    if (sizeX <= 0 || sizeY <= 0) return false;

    // allocate 2D table
    table = new int* [sizeX];
    
    for (int i = 0; i < sizeX; i++) {
        table[i] = new int[sizeY];
    }

    cout << endl << "Table " << sizeX << " x " << sizeY << endl;
    for (int i = 0; i < sizeX; i++) {
        cout << endl;
        for (int j = 0; j < sizeY; j++) {
            table[i][j] = i + j; //initializing elements of the array
            cout << table[i][j] << ", ";
        }
    }

    return true;
}
bool deallocateTwoDimTable(int (** &table), int sizeX) {
    if (sizeX <= 0) return false;

    for (int k = 0; k < sizeX; k++) {
        delete[] table[k];
    }

    delete[] table;

    return true;
}
int main() {

    int** table = nullptr;

    const int sizeX = 5; // rows
    const int sizeY = 3; // columns

    try {    
        const bool allocationResult = allocateTwoDimTable(table, sizeX, sizeY);
        cout << endl << "allocation result: " << (allocationResult ? "true" : "false") << endl;

        const bool deallocationResult = deallocateTwoDimTable(table, sizeX);
        cout << endl << "deallocation result: " << (deallocationResult ? "true" : "false");
    }
    catch (std::exception& e)
    {
        std::cout << e.what();
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}

Upvotes: 2

Chris Golden
Chris Golden

Reputation: 54

have a look at this answer https://stackoverflow.com/a/936709/9936992 they are also mentioning the possibility to use a single array that will mimic the two D array

Upvotes: 1

Vlad from Moscow
Vlad from Moscow

Reputation: 310960

You have to pass the pointer by reference. Otherwise the function allocateTwoDimTable will deal with a copy of the value of the original pointer. That is changing the copy will not influence on the original pointer.

Also the parameters sizeX and sizeY should have the type size_t because in general the type int can be unable to specify required dimensions of arrays.

The function can be declared like

bool allocateTwoDimTable( int ** &table, size_t sizeX, size_t sizeY);

Pay attention to that you are created uninitialized arrays

table[i] = new int[sizeY]

So outputting them

cout << table[i][j] << ", ";

invokes undefined behavior.

Upvotes: 1

Related Questions