0
#include <iostream>

using namespace std;

void create(int** map);

int main() {
    int** map;
    create(map);
    cout << endl << "printing map in main" << endl;
    for (int i = 0; i < x; i++) {
        for (int j = 0; j < y; j++) {
            map[i][j] = 1;
            cout << map[i][j] << " ";
        }
        cout << endl;
    }
    return 0;
}

void create(int** map) {
    int x = 8, y = 8;

    map = new int* [x];

    for (int i = 0; i < x; i++) {
        map[i] = new int[y];
    }
    for (int i = 0; i < x; i++) {
        for (int j = 0; j < y; j++) {
            map[i][j] = 1;
            cout << map[i][j] << " ";
        }
        cout << endl;
    }
}

I've been trying to read in the elements from 2D pointer that is pointing to a dynamic array in main function but i can't seem to get it work, i've tried reading it using double for loops and ((map + i) + j) but to no avail

3
  • Your program seems to work fine. It prints out a 2D array containing 64 1s. Commented Dec 23, 2021 at 7:41
  • yes, however when i tried to cout each element from main function it throws segmentation fault Commented Dec 23, 2021 at 7:50
  • Print the value of map before and after create(map), that may explain at least part of your problems. Commented Dec 23, 2021 at 13:42

3 Answers 3

3

Your code with a bit of refactoring:

#include <iostream>


int** create2DArray( const std::size_t rowCount, const std::size_t colCount );
void delete2DArray( int** const array2D, const std::size_t rowCount );
void print2DArray( int** const array2D, const std::size_t rowCount, const std::size_t colCount );

int main( )
{
    constexpr std::size_t ROW_COUNT { 8 };
    constexpr std::size_t COL_COUNT { 8 };

    int** map { create2DArray( ROW_COUNT, COL_COUNT ) };

    std::cout << '\n' << "printing map in main" << '\n';
    print2DArray( map, ROW_COUNT, COL_COUNT );

    // after work is done with array, delete it
    delete2DArray( map, ROW_COUNT );
    map = nullptr; // to prevent it from becoming a dangling pointer

    return 0;
}

int** create2DArray( const std::size_t rowCount, const std::size_t colCount )
{
    int** const array2D = new int* [rowCount];

    for ( std::size_t row = 0; row < rowCount; ++row )
    {
        array2D[row] = new int[colCount];
    }

    for ( std::size_t row = 0; row < rowCount; ++row )
    {
        for ( std::size_t col = 0; col < colCount; ++col )
        {
            array2D[row][col] = 1;
        }
    }

    return array2D;
}

void delete2DArray( int** const array2D, const std::size_t rowCount )
{
    for ( std::size_t row = 0; row < rowCount; ++row )
    {
        delete[] array2D[row];
    }

    delete[] array2D;
}

void print2DArray( int** const array2D, const std::size_t rowCount, const std::size_t colCount )
{
    for ( std::size_t row = 0; row < rowCount; ++row )
    {
        for ( std::size_t col = 0; col < colCount; ++col )
        {
            std::cout << array2D[row][col] << " ";
        }

        std::cout << '\n';
    }
}

The output:


printing map in main
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1

Note #1: When constexpr is used in the declaration of a variable, that variable is evaluated at compile-time and not run-time and becomes a constant expression. So it's good practice to declare variable with constant value (e.g. an immediate like 5 or 3.7) as constexpr.
Check constexpr (C++) for more details.

Note #2: std::size_t is an unsigned integral type. On my compiler it is the equivalent of unsigned long long int (which BTW has a size of 8 bytes).
Here it is from this std::size_t:

typedef /*implementation-defined*/ size_t;
Sign up to request clarification or add additional context in comments.

7 Comments

@UniversE Well, it's now fixed.
@xentuous Check the updated answer in which I show you how to delete the 2D array after your work is done with it. If you don't delete it, then that will lead to a memory leak which is an unwanted phenomenon in programming.
that, and the other edits, converted the downvote to an upvote. It's a decent answer now.
@UniversE Oops! Forgot to assign nullptr to map after it gets deleted. Now that is covered too.
@digito_evo: Hm, just out of curiosity. I can see that you are good programmer and know the language. But do you think the the OP already knows things like constexpr and std::size_t and things and real C++ design? My guess is: No. Still in learning phase. So, your answer would be really VERY good, if you had explained something and not just dropped the code . . .
|
1

You need to declare the parameter as having a referenced type. For example

void create(int ** &map);

In this case the pointer map declared in main will be changed within the function.

Otherwise the function deals with its local variable (parameter) map and the pointer map declared in main will be unchanged..

Also it is a bad idea to use magic numbers like 8. The function will be more flexible and general if the sizes of an array can be passed to the function. For exampele

void create( int ** &map, size_t m, size_t n ) 
{
    map = new int * [m];

    for ( size_t i = 0; i < m; i++ ) 
    {
        map[i] = new int[n];
    }

    for ( size_t i = 0; i < m; i++ ) 
    {
        for ( size_t j = 0; j < n; j++ ) 
        {
            map[i][j] = 1;
            cout << map[i][j] << " ";
        }
        cout << endl;    
    }
}

And in main you could write

size_t m = 8, n = 8;

int **map  = nullptr;

create( map, m, n );

cout << endl << "printing map in main" << endl;

for ( size_t i = 0; i < m; i++ ) 
{
    for ( size_t j = 0; j < n; j++ ) 
    {
        cout << map[i][j] << " ";
    }
    cout << endl;
}

3 Comments

Downvote, because this encourages an obviously unexperienced user to workaround a code design flaw by applying another code design flaw. Instead, the create function should return the map.
@ArminMontigny okay, then please tell me this: is create() in this scenario supposed to free any memory already present in the object map referes to? If not, why? If so, why? Who even owns this piece of memory (in terms of formally determining ownership)? If you don't free, you require the input to be uinitialized, so what's the point in passing it as argument at all? If you do free, then the above code doesn't make any sense, because you would need to allocate memory outside of create() just to be thrown away. It really, really, makes absolutely no sense.
@ArminMontigny because the heated comments have been deleted and it might be hard for future visitors to follow our conversation, I give a brief summary first: I criticized this answer for "teaching" bad practice instead of giving a proper solution and then things went sideways really quickly. Now your point is, that Vlads answer is the most narrow solution to make the OP code work. While this is true, I still disagree that we only give the narrowest (or least invasive) "fix" to the code. Instead we should show a good way to write the code. Never teach bad things, even with good intentions.
0

Instead of passing a pointer to create() you should return it. Like this:

int main(){
    int **map = create();
    cout << endl << "printing map in main" << endl;
    return 0;
}

int ** create() {
    int x = 8, y = 8;

    int ** map = new int* [x];

    for (int i = 0; i < x; i++) {
        map[i] = new int[y];
    }

    for (int i = 0; i < x; i++) {
        for (int j = 0; j < y; j++) {
            map[i][j] = 1;
            cout << map[i][j] << " ";
        }
        cout << endl; 
    }
   
    return map;
 }

Also you should add a delete for the allocated matrix.

1 Comment

the reason i'm using pointer as an array is because this is part of a code fragment which i need to dynamically allocate an arbitrary value of x and y values by reading a text file in the create() function, the idea is that in the main function, i will declare int** map; and i will call a create() function to initialise the 2d array and some string values from the text file before proceeding with the main program functionality. pls advise where possible

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.