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 arrremains 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.
Related
I am under the assumption that the code bellow is a unique_ptr to an array (aka not what I want)
std::unique_ptr<int[]> arr;
arr = std::make_unique<int[]> (5);
arr[0] = *new int(1);
delete &arr[0]; // malloc error, want to avoid "delete"
However, I want an array that holds unique_ptrs like so...
std::unique_ptr<int> arr2 []; //Error, requires explicit size
arr2 = std::make_unique<int> [5]; //Desirable, does not compile
arr2[0] = std::make_unique<int>(1); //Desirable, does not compile
How do I go about making an array of unique_ptrs? If that is not possible, then how do I deal with a malloc error?
Do you want an array that holds unique_ptrs (as in the title), or a unique_ptr holding an array (as in your examples)?
If an array of unique_ptrs is what you want, then
std::vector<std::unique_ptr<int>>
or
std::array<std::unique_ptr<int>, 3>;
(for example) will do the job.
If a unique_ptr holding an array is what you're after, then unique_ptr<int[]> will work (there is a partial specialisation of unique_ptr to support it), although you can't use std::make_unique and will need to call operator new[] yourself:
std::unique_ptr<int[]> p{new int[42]};
However, if you think you need this, what you most likely really want is std::vector, and I'd strongly recommend using that instead.
Short answer: use vectors. They are much easier to work with and you don't have to explicidly allocate memory. You should also use typedefs for syntax simplicity.
typedef unique_ptr<int> intPtr;
vector<intPtr> vec;
vec.push_back(make_unique<int>(69));
auto myIntPtr = make_unique<int>(16);
vec.push_back(move(myIntPtr)); // unique ptrs cannot be copied, must be moved
unique_ptr<int[5]> p1; // valid syntax
std::unique_ptr<int[]> arr;
arr = std::make_unique<int[]> (5);
At this point you have a unique_ptr to an array of int. This sounds like it is exactly what you want.
arr[0] = *new int(1);
But this is questionable. It dynamically allocates a single int, assigns 1 to the allocated int, then it assigns the value, 1, at the allocated int into the array at element 0. the allocated int is left hanging with nothing pointing at it, and is now exceptionally difficult to `delete. This is a memory leak.
delete &arr[0]; // malloc error, want to avoid "delete"
And as you've seen, this is fatal. Rather than attempting to delete the leaked int, delete has been invoked with a pointer to the array stored in the unique_ptr. Eventually the unique_ptrwill try todelete` the array and fail because it's already gone.
Based on comments, OP intends
std::unique_ptr<int*[]> arr;
arr = std::make_unique<int*[]> (5);
arr[0] = new int(1);
delete arr[0];
But I'd like to talk them out of this idea. Let's look at their end goal: a templated class
template <class TYPE>
class MyVector
{
std::unique_ptr<TYPE[]> arr; // array of whatever type
public:
MyVector(size_t size): arr(std::make_unique<TYPE[]> (size))
{
}
TYPE& operator[](size_t index)
{
return arr[index];
}
// note the complete lack of growing, shrinking and other vector goodness
// as they are not needed for this example.
};
We can use this class with just about anything.
int main()
{
// vector of int
MyVector<int> vec(5);
vec[0] = 1;
// vector of pointer to int (yuck)
MyVector<int*> vec2(5);
vec2[0] = new int(1);
delete vec2[0];
// vector of smart pointer to int (also yuck, but less yuck)
MyVector<std::unique_ptr<int>> vec3(5);
vec3[0] = std::make_unique<int>(1);
// vector of std::string
MyVector<std::string> vec4(5);
vec4[0] = "I am the very model of a modern major general...";
}
If the user of the vector want it to contain pointers, they can say so. There is no reason to force the user to use a pointer.
Quick question. Will this leak and why/ why not?
int main()
{
int array[] = {1,2,3};
doStuff(array);
return 0;
}
when doStuff will do something like this
void doStuff(int * arr)
{
// ...
arr = new int [50];
// ...
}
EDIT for #Scott Hunter
I think it won't leak because array points to memory on stack and I've never heard of memory leaking from stack, but on the other hand i kinda lose any link to this memory.
EDIT2
My problem was I was thinking that changing arr in doStuff address will change array in main as well but it won't.
Yes it will leak, since you don't call delete [] arr; anywhere inside of doStuff().
Note that you don't even change the int array[]; declared outside of the function.
All you are doing is to change a copy of that pointer that was passed as by value parameter.
As an aside recommenation:
Don't use raw pointers and raw arrays in c++. Rather use a std::vector<int> for your case, and forget about dynamic memory management at all.
doStuff takes a copy of the array pointer. Setting arr to something else inside the body of doStuff will not modify the original array value in main.
Therefore, unlesss you call delete[] arr inside doStuff, your code will leak.
I am converting a vector of doubles to an array of doubles as seen here:
The difference is, that I want to return the pointer a as a function parameter:
void getArray(double* a)
{
std::vector<double> v;
a = &v[0];
}
So my question is, when does the memory of a gets deallocated? Or do I have to call delete[] a by myself, which seems strange since I did't allocate the memory with new. I have read the comments to the above mentioned answer but it still isn't clear to me.
The memory pointed to by a gets deallocated when the vector v is destructed. In this case, that's at the end of the function getArray.
This implementation would invoke undefined behavior because v is local:
void getArray(double* a)
{
std::vector<double> v;
a = &v[0]; // would be a UB for returning the pointer to internals of a local variable.
}
However, the caller will never see any effect of this, because modifications to a stay local to getArray function.
If you want to make an array out of a vector, allocate a new array, use std::copy to copy the content into it, and return the array to the caller. Make sure the callers call delete[] on the result once they are done with the copyL
double *getArray(const vector<double>& v) {
double *res = new double[v.size()];
std::copy(v.begin(), v.end(), res);
return res;
}
The caller should use it as follows:
vector<double> data;
data.push_back(...);
... // populate the vector
double *tmp = getArray(data);
... // Use the array
delete[] tmp; // Avoid memory leaks
Don't do this:
void getArray(double* a)
{
std::vector<double> v;
a = &v[0];
} // The vector is destroyed here, and the memory
// is deallocated.
In any case, you're not modifying the a pointer outside of your function, so you won't get the desired effect.
Instead, return the vector and use it directly. Or, in general, use vectors throughout your code. If you need to pass them in to a function that expects a pointer to an array, you can pass &v[0] there. Such a function usually expects the size too. For this, pass v.size(). You can do this safely as long as that function doesn't take ownership, or deallocate the memory.
Note, also, that a vector declared as std::vector<double> v; does not have a size, so attempting to access the first element, as in v[0] is also undefined behaviour. At the very least, you need to give the vector a size (pass a size to its constructor) to ensure some memory is allocated. You should always make sure the vector has some allocated memory before indexing into it, including when trying to take the address of the first element.
What you probably want to do is:
std::vector<double> getArray() {
std::vector<double> v = /* some sane initialisation */;
return v;
}
// some time later, assuming a function:
// void do_something(double* a, size_t n);
// ...
std::vector<double> v = getArray();
if (v.size()) {
do_something(&v[0], v.size());
} else {
// fail gracefully
}
when does the memory of a gets deallocated?
The a pointer itself is a local variable, so it is deallocated at the end of its scope.
a points to the memory allocated by the vector v. The pointed memory is deallocated in the destructor of v (The memory may also be deallocated if objects are added to or removed from the vector). And because v is a local variable, it is destroyed at the end of scope.
Or do I have to call delete[] a by myself,
No, because the memory is owned by the vector object, but also because
which seems strange since I did't allocate the memory with new.
Exactly. You didn't call new[], so you don't call delete[].
Note that v[0] has undefined behaviour because the vector is empty.
I'm using the code above to dynamically allocate an array, do some work inside the function, return an element of the array and free the memory outside of the function. But when I try to deallocate the array it doesn't free the memory and I have a memory leak. The debugger pointed to the myArray variable shows me the error CXX0030. Why?
struct MYSTRUCT
{
char *myvariable1;
int myvariable2;
char *myvariable2;
....
};
void MyClass::MyFunction1()
{
MYSTRUCT *myArray= NULL;
MYSTRUCT *myElement = this->MyFunction2(myArray);
...
delete [] myArray;
}
MYSTRUCT* MyClass::MyFunction2(MYSTRUCT *array)
{
array = (MYSTRUCT*)operator new(bytesLength);
...
return array[X];
}
The only time you should use delete[] is when you've allocated with new[], but that's not what you're doing. You're using operator new, which isn't what you should use for general-purpose array allocation. Use new[] instead. Or use a vector.
Furthermore, although you pass myArray to MyFunction2 as array and then assign a new value to array inside the function, that doesn't change the value of myArray in the caller. That variable retains its original null value, so your delete[] call does nothing. You can change array to be passed by reference instead of by value so changes to it will be reflected in its actual parameter in the caller.
You allocate the array in MyFunction2, but you don't return its address. The argument to MyFunction2 is by value, so you pass a copy of myArray to it when you call it, but the function itself can never change the value of the caller's local variable.
The simple and obvious answer to your problem is to declare the parameter of MyFunction2 to be a reference, e.g.:
MYSTRUCT* MyClass::MyFunction2(MYSTRUCT*& array)...
A much better solution, however, would be to use std::vector, and not worry about the deallocations.
You allocate the array inside of MyFunction2 and never free it. And in the MyFunction1 you delete[] the null pointer, which is a no-op. I'm not sure I can tell you what you should've done instead, because your intentions aren't clear.
Ive been faced with a problem recently that I can't think of a good way to solve. I'm using a case structure to attempt to set attributes to a "character" that will be passed to an object constructor.
Example:
//note this is inside a function with a return type of int*
int selection;
cin >> selection;
int * iPtr;
switch(selection){
case 1:{
int anArray[6] = {8,5,2,4,250,100} // str, dex, int, luck, hp, mp
iPtr = anArray;
return iPtr;
}
//more cases and such below
The issue that I'm having is that when I return my pointer it seems to be filled with a good amount of junk, rather than the information, rather than the information that I would be expecting it to hold. Is that because the array gets destroyed at the end of the scope? If so what should I do to make this work out how I'm hoping for it to (getting a pointer with the values that I want).
Thanks!
Yes - anArray is declared on the stack. When the function exits, its stack frame is reclaimed, so it's no longer valid to refer to that memory. If you want the array to persist, allocate it on the heap instead:
int* anArray = new int[6]; // and initialize
return anArray;
Just remember to clean it up later at some point with the corresonding delete[].
EDIT
You should prefer to use something that automatically manages resources for you, like in Praetorian's answer, so that you don't accidentally leak memory.
Yes, the array you've declared is indeed local to the function and no longer exists once the function exits. You can dynamically allocate an array using new and then have the caller delete[] the memory (but don't do this!), or modify your function to return an std::unique_ptr instead of a raw pointer.
unique_ptr<int[]> anArray (new int[6]);
// do initialization
return anArray;
Now, the caller doesn't have to worry about freeing memory allocated by the function.
EDIT:
There are a couple of different ways to perform initialization of the unique_ptr.
anArray[0] = 8;
anArray[1] = 5;
// etc ...
OR
int init[6] = {8,5,2,4,250,100};
std::copy( &init[0], &init[0] + 6, &anArray[0] );
Yes, it's because the local array is overwritten as the program runs. You can either declare the array static in the method (which would be a good idea for a fixed array like this), declare it at global scope, or allocate an array with new to return. The last alternative gives you the opportunity to have a different array returned for each call, but remember to deallocate the arrays after use.
In C++, the best answer is not to return a pointer. Instead, use a proper object instead of a C array or manually allocated memory and return this object:
std::vector<int> f() {
std::vector<int> array;
// fill array
return array;
}
Using new int[x] (or whatever) is really, really deprecated in modern C++ code and is only deemed acceptable under very special circumstances. If you use it in normal code, this is a very obvious place for improvement. The same goes for other uses of manually managed memory. The whole strength of C++ lies in the fact that you don’t have to manage your own memory, thus avoiding a multitude of hard to track bugs.
Yes, it is because the array you created is created on the stack, and when you return, the part of the stack that you were at is overwritten (presumably by a debug process).
To avoid this, you would write
int* anArray = new int[6];
// fill the array
return anArray;
In this case, you will also have to delete the returned result when you are finished with it, such as in
int* dataArray = getTheArray();
// Use the dataArray
delete [] dataArray;
Allocate array on the heap
int* anArray = new int[6];
You will have to delete it manually:
delete[] iPtr;