Recommended way to return a reference from a function in C ++

I used this approach to return references from C ++ functions. However, I suspect that there are better patterns for performing such operations. Also, I assume this approach involves a memory leak.

class A {};
A& return_instance_of_A(){
    A* result = new A();
    return *result;
}

      

Would using shared_ptr be the best choice?

+3


source to share


1 answer


What is the recommended way to return a link from a function?

Syntactically just return the link.

int& myFunction() { .... }

      

Links behave almost like pointers. There are some problems in your example.

The object you are allocating has to be removed at some point, and this is usually handled using pointers. Canonically, it is very strange to receive a link that you need later delete

.

It is also not common in modern C ++ to handle memory allocations in this disabled way. I agree with your offer for a refund shared_ptr

. This makes the ownership explicit and does not accidentally leak memory as your example might.

Your example does not necessarily cause a memory leak, but it is inconvenient because you are placing certain requirements on the caller (namely the delete

returned object) that are not met by the compiler.


Edit to appeal to people suggesting return by value: it just depends on the caller's requirements. Many objects of small and useful information, such as Rectangle

or Size

, are designed to be passed by value, which makes things very simple and intuitive.

A practical example of this would be the following:

inline Rect make_square_rect(int left, int right, int width)
{
  return Rect(left, right, width, width);
}

      

It is definitely best to return such a function by value. Note how this function works with the constructor, though ...

For other larger, more devoted and stateful objects such as TcpConnection

or Window

, this similarity becomes clearer. The issue of ownership and memory management is on the rise.



The same applies to anything that cannot be copied / moved.

Thus, creating a new Window

one cannot be as random as with Rect

. Making a Rect

function like yours doesn't really care much about the ownership issue because of how cheap and easy it is to copy the object Rect

. But if your function returns something like this Window

, then naturally your function will access its own value - probably by returning shared_ptr<Window>

.


Edit # 2: the nature of the constructor

In response to your comments, I would like to point out again that these functions are very similar to constructors. These functions should really just set up an object for first use - but we're sitting here trying to decide how the function should handle ownership / copying.

Indeed, this is exactly what the constructor is supposed to do.

struct BigInteger
{
    BigInteger(int initial_value) { ... }
};

      

Here, the designer does not need to deal with the concepts we are talking about. The caller decides how he wants to handle the ownership:

BigInteger* ptr = new BigInteger(42);
BigInteger val = BigInteger(42);

      

Written as a constructor, this can handle both cases. The way I see it is annoying in this situation that constructors cannot be called in C ++. For example, imagine you are writing these functions:

BigInteger make_big_integer_by_multiplying(int a, int b) { ... }
BigInteger make_big_integer_by_adding(int a, int b) { ... }

      

There is no good way to turn them into constructors. You need a symbol name to differentiate these functions, and constructors cannot have names.

Written as a standalone function, you are forced to make decisions about owner behavior. You should just weigh the pros and cons, and basically: think about how subscribers want to use the object. If callers need a persistent, persistent stateful object, then return shared_ptr

. If callers will use the object as an intermediate, value type (which I would BigInteger

absolutely assert), then return its value.

+6


source







All Articles