Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ correct way to return pointer to array from function

I am fairly new to C++ and have been avoiding pointers. From what I've read online I cannot return an array but I can return a pointer to it. I made a small code to test it and was wondering if this was the normal / correct way to do this:

#include <iostream> using namespace std;  int* test (int in[5]) {     int* out = in;     return out; }  int main() {     int arr[5] = {1, 2, 3, 4, 5};     int* pArr = test(arr);     for (int i = 0; i < 5; i++) cout<<pArr[i]<<endl;     cout<<endl;     return 0; } 

Edit: This seems to be no good. How should I rewrite it?

int* test (int a[5], int b[5]) {     int c[5];     for (int i = 0; i < 5; i++) c[i] = a[i]+b[i];     int* out = c;     return out; } 
like image 436
asimes Avatar asked Oct 20 '12 21:10

asimes


People also ask

How do you return a pointer from a function in C?

Return Function Pointer From Function: To return a function pointer from a function, the return type of function should be a pointer to another function. But the compiler doesn't accept such a return type for a function, so we need to define a type that represents that particular function pointer.

Is it possible to return of pointer from a function?

We can pass pointers to the function as well as return pointer from a function. But it is not recommended to return the address of a local variable outside the function as it goes out of scope after function returns.


2 Answers

Your code as it stands is correct but I am having a hard time figuring out how it could/would be used in a real world scenario. With that said, please be aware of a few caveats when returning pointers from functions:

  • When you create an array with syntax int arr[5];, it's allocated on the stack and is local to the function.
  • C++ allows you to return a pointer to this array, but it is undefined behavior to use the memory pointed to by this pointer outside of its local scope. Read this great answer using a real world analogy to get a much clear understanding than what I could ever explain.
  • You can still use the array outside the scope if you can guarantee that memory of the array has not be purged. In your case this is true when you pass arr to test().
  • If you want to pass around pointers to a dynamically allocated array without worrying about memory leaks, you should do some reading on std::unique_ptr/std::shared_ptr<>.

Edit - to answer the use-case of matrix multiplication

You have two options. The naive way is to use std::unique_ptr/std::shared_ptr<>. The Modern C++ way is to have a Matrix class where you overload operator * and you absolutely must use the new rvalue references if you want to avoid copying the result of the multiplication to get it out of the function. In addition to having your copy constructor, operator = and destructor, you also need to have move constructor and move assignment operator. Go through the questions and answers of this search to gain more insight on how to achieve this.

Edit 2 - answer to appended question

int* test (int a[5], int b[5]) {     int *c = new int[5];     for (int i = 0; i < 5; i++) c[i] = a[i]+b[i];     return c; } 

If you are using this as int *res = test(a,b);, then sometime later in your code, you should call delete []res to free the memory allocated in the test() function. You see now the problem is it is extremely hard to manually keep track of when to make the call to delete. Hence the approaches on how to deal with it where outlined in the answer.

like image 106
vvnraman Avatar answered Oct 02 '22 11:10

vvnraman


Your code is OK. Note though that if you return a pointer to an array, and that array goes out of scope, you should not use that pointer anymore. Example:

int* test (void) {     int out[5];     return out; } 

The above will never work, because out does not exist anymore when test() returns. The returned pointer must not be used anymore. If you do use it, you will be reading/writing to memory you shouldn't.

In your original code, the arr array goes out of scope when main() returns. Obviously that's no problem, since returning from main() also means that your program is terminating.

If you want something that will stick around and cannot go out of scope, you should allocate it with new:

int* test (void) {     int* out = new int[5];     return out; } 

The returned pointer will always be valid. Remember do delete it again when you're done with it though, using delete[]:

int* array = test(); // ... // Done with the array. delete[] array; 

Deleting it is the only way to reclaim the memory it uses.

like image 22
Nikos C. Avatar answered Oct 02 '22 10:10

Nikos C.