Dynamic allocation in function not accessible outside

I need multiple multi-dimensional arrays to be dynamically allocated in a function. The required size is determined inside the function and their values are then assigned there too. My issue is that i am not able to access the assigned array values outside the function. Running the code below I get EXC_BAD_ACCESS

1
2
3
4
5
6
int* a1;
int* a2;
ini_array(a1,a2);
std::cout<<a1[0];
delete[] a1;
delete[] a2;


1
2
3
4
5
void ini_array(int* a1,int* a2){
    size_t size=4;
    a1=new int[size];
    a2=new int[size];
}


thanks
The parameters a1 and a2 are passed by value; a1 and a2 in the function are copies.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <cstddef>

// returns the size (required; the caller needs to know this)
std::size_t ini_arrays( int*& a1, int*& a2 ) // pointers are passed by reference
{
    std::size_t size = 4 ; // determined inside the function

    a1 = new int[size] {} ;
    a2 = new int[size] {} ; // note: this is not exception safe
                            //       we leak resources if this throws

    return size ;
}

#include <array>
#include <vector>

// exception safe and cleaner version
std::array< std::vector<int>, 2 > ini_arrays()
{
    std::size_t size = 4 ; // determined inside the function
    return { { std::vector<int>(size), std::vector<int>(size) } } ;
}

int main()
{
    {
        int* a1 = nullptr ;
        int* a2 = nullptr ;

        const std::size_t n = ini_arrays( a1, a2 ) ;
        for( std::size_t i = 0 ; i < n ; ++i ) { a1[i] = 1 ; a2[i] = 2 ; }
    }

    {   
        // C++17: http://en.cppreference.com/w/cpp/language/structured_binding
        auto [a1,a2] = ini_arrays() ;
        for( int& v : a1 ) v = 1 ; // http://www.stroustrup.com/C++11FAQ.html#for
        for( int& v : a2 ) v = 2 ;
    }
}
would you mind explaining why the first option isn't exception safe, and why the curly brackets are necessary?

Thanks
> would you mind explaining why the first option isn't exception safe

If the first new (line 8) doesn't throw, and the second new (line 9) throws, there would be a problem.

Compare with:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// returns the size (required; the caller needs to know this)
std::size_t ini_arrays( int*& a1, int*& a2 ) // pointers are passed by reference
{
    std::size_t size = 4 ; // determined inside the function

    a1 = new int[size] {} ;

    try
    {
        a2 = new int[size] {} ;
        return size ;
    }

    catch( ... )
    {
        // first, clean up the mess
        delete[] a1 ;
        a1 = a2 = nullptr ;

        throw ; // then rethrow the original exception
     }
}



> and why the curly brackets are necessary?

They are not necessary; but using them may be a good idea (initialize all the values to zeroes).
1
2
3
int* a = nw int[4] ; // no initialisation is performed
int* b = new int[4] {} ; // empty initializer: value initialisation  (zero initialisation).
int* c = new int[4] { 1, 2, 3, 4 } ; // list initialisation (aggregate initialisation) 
Topic archived. No new replies allowed.