简体   繁体   中英

Array as return value of a function

Is there a way to return an array as a result of a function in c++?

int* returnArray()
{
    int* arr = new int[3];
    return arr;  
}

This way arr is a local variable and the alocated memory block is lost after the function returns. Is there any way around this besides defining an array outside the function block?

Allocated memory block is not lost, since the memory is allocated on the heap. The pointer to this memory is copied, and correctly returned to the caller. In other words, there is nothing wrong with your code - except possibly for the fact that the caller must know the array size in order to do anything useful with the returned array.

The anti-pattern you are probably referring to looks like this:

// WRONG: returns pointer to local data
int* returnArray() {
   int arr[3] = {1, 2, 3};
   return arr;
}

This is an error because arr is allocated on the stack, and the function returns a pointer to that data. To fix it, one would need to declare the function as returning an array, but C++ doesn't allow this, so it must be done indirectly. Fixed function would then look like this:

struct Array {
    int array[3];
};

// correct: generated copy constructor correctly copies arr
Array returnArray() {
    Array arr = {{1, 2, 3}};
    return arr;
}

In production code, and if you can use C++11, your function would simply return std::array<int, 3> . C-style arrays are almost always used in low-level code to implement containers and there is almost never a need to directly return them from functions.

You're returning a pointer to an array it's OK, but the problem is "who is responsible to delete it", you can use smart pointers:

std::unique_ptr<int[]> returnArray()
{
    std::unique_ptr<int[]> arr (new int[3]);
    return arr;  
}

And everyone is happy. Also, you can use std::vector .

std::vector<int> returnArray()
{
    std::vector<int> arr(3);
    return arr;  
}

Your function is okay as is. Memory obtained with a new expression is never deallocated until you use a delete expression.

This is the version that would lose the memory when the function returns:

// WRONG:
int* returnArray()
{
    int arr[3];
    return arr;
}

The even better way would be to return a std::vector<int> .

What you have works; the issue is that you've made the caller responsible for remembering to delete the dynamic array. This is a good recipe for a memory leak.

Perhaps you were thinking of trying to return a local array:

int * returnArray() {
    int arr[3];
    return arr;   // BOOM! dangling pointer
}

This is wrong, since this array is destroyed when the function returns; using the pointer after that will give undefined behaviour.

To solve both issues, return a managed dynamic array:

std::vector<int> returnVector() {
    std::vector<int> v(3);
    return v;
}

Actually, you're code is fine but dangerous, I mean, allocated memory for arr remains until you call delete[] on it, meaning that you can safely access array's elements but delegating memory clean up to source code using this method is a bad practice and will, most probably, lead to a memory leak or corruption.

I would recommend passing the array as a parameter so calling code is in charge of memory management:

void returnArray(int* arr)
{
    ... Your code here managing array's contents ...
}

Or, if this is one class' method, manage this memory from inside this class.

Edit: Or better, use smart pointers as suggested by @M M.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM