Reputation: 273
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()
Upvotes: 3
Views: 34930
Reputation: 4196
In C++, you can't return a variable of an array type (i.e. 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
Upvotes: 5
Reputation: 63124
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).
Upvotes: 11
Reputation: 27756
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:
delete
).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.resize()
method for instance).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';
}
}
Upvotes: 4
Reputation: 42924
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).
Upvotes: 0