简体   繁体   中英

C++ How to return dynamically allocated array from function

I have just started learning C++. I am reading the tutiorials in internet and now I made a dynamically allocated array in function.

void array_() {
    int size;
    cin >> size;

    int * Array = new int[size];


    for (int i = 0; i < size; ++i)
        cin >> Array[i];
}

How to return this function to main()

Well, it would be wise to return the size as well as the pointer, because otherwise there'll be no way of using the resulting array safely.

So we're looking for a way to return two values from a function. This can be done by taking a reference parameter, through which you assign one of the values:

int *array_(int &size) {
    std::cin >> size;

    int *Array = new int[size];

    for (int i = 0; i < size; ++i)
        std::cin >> Array[i];

    return Array;
}

int main() {
    int size;
    int *arr = array_(size);
    // ...
    delete[] arr; // Don't forget to delete[] what has been new[]'d!
}

Or, you could return a std::pair containing both values:

std::pair<int *, int> array_() {
    int size;
    std::cin >> size;

    int * Array = new int[size];

    for (int i = 0; i < size; ++i)
        std::cin >> Array[i];

    return {Array, size};
}

int main() {
    auto arr = array_(size);
    // ...
    delete[] arr.second; // Don't forget still!
}

But both of these are crazy bad ideas, so you could start right now to write actual C++ so it doesn't look like deformed C, using standard containers:

std::vector<int> array_() {
    int size = 0;
    std::cin >> size;

    std::vector<int> vec(size);

    for(int &i : vec)
        std::cin >> i;

    return vec;
}

int main() {
    auto arr = array_(size);
    // ...
    // Now you can forget delete: no raw owning pointer, no worries.
}

Simple, leak-proof and exception-safe (well, ideally you'd sanitize user input too).

In C++ in most cases we don't need to manually allocate resources using operator new .

I suggest to use std::vector<int> instead. It has the following advantages over a dynamically allocated plain array:

  • It will automatically deallocate the reserved memory when the scope exits (you don't have to call delete ).
  • It has a size() method so you always know how many elements are contained in the vector. Compare that with a dynamic plain array where you would have to store the size in another variable.
  • You can change the size of the "array" dynamically after construction (using the resize() method for instance).

Example

std::vector<int> array_() 
{
    int size;
    cin >> size;

    // Create a dynamic "array" with the given size.
    std::vector<int> result( size );

    for (int i = 0; i < size; ++i)
        cin >> result[i];

    return result;
}

To use that "array" from main() :

int main()
{
    // Call function array_() and store the result in variable v.
    std::vector<int> v = array_();

    // Print all elements of v using range-based loop.
    for( int x : v )
    {
        std::cout << x << '\n';
    }

    // Alternatively print all elements using classic loop with index.
    for( int i = 0; i < v.size(); ++i )
    {
        std::cout << v[i] << '\n';
    }
}

In C++, you can't return a variable of an array type (ie int arr[] ) from a function "as is", though you can return a reference or a pointer to an array . That is some fairly clumsy syntax though. In the code shown, there is no array , rather a pointer to a chunk of dynamically allocated memory. The main problem however is that since the memory is dynamically allocated, when you return a pointer to that memory, you only give the client half the information: the size of the array remains unknown.

Thus, if you really want to stick to traditional arrays allocated dynamically, you can pass the size of the array as a reference parameter ("out-value") to a function like so:

int* func(std::size_t& size_out) {
    // int n = ...;
    int* array = new int[n];
    size_out = n;
    return array;
}

int main() {
    int size;
    int* result = func(size);
    delete[] result;
    result = nullptr;
}

As you can see, a side-effect of manually allocating memory is that the client takes responsibility of it, and you have to manually delete it outside of the function where it was allocated .

But "out-values" are a bad style really, especially in API's. Avoid them whenever you can!

It's of course better to use a proper dynamic array facility such as a std::vector<T> , but that seems to not be the point of the exercise.

Reference used: Return array in a function

You can return the dynamically allocated array returning its pointer:

int* ProduceArray() {
    ...
    int* arrayPtr = new int[size];
    ...
    return arrayPtr;
}

However, note that in his way you loose the important information of the size of the array (which is very important for the code that consumes the array, to avoid buffer overruns).

In modern C++ a better approach is to return a standard library container like std::vector , instead of raw pointers.

Note that std::vector instances do know their size, and automatically release their memory as well (instead you must explicitly call delete[] when you have raw owning pointers).

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