Tki Lio
Tki Lio

Reputation: 263

Returning an object from a function in C++: its process and nature

I'm quite confused about returning an object from a function. For example:

class A
{
public:
    ~A(){}
};

A find()
{
    ...
    A a;
    return a; 
}

Does it return "a" by reference or by value? Moreover, does "find" delete "a" first, then return or return first, then delete "a"?

Upvotes: 0

Views: 89

Answers (2)

ANjaNA
ANjaNA

Reputation: 1426

In your function, you are returning a value, not reference.

A find();

return type is A. Is is value, a copy of a will return.

In order to return a reference, you should write your function as follows.

A& find();

return type A& means a reference to A. But your function body should be change accordingly, in order to return a valid reference.

With the current implementation, you are creating object a inside the function. So it get delete when it goes out of the scope, at the end of function execution.

Your question "Moreover, does "find" delete "a" first, then return or return first, then delete "a"?"

copy of a will return first, then a will delete.

If you return a reference, reference will be return, then object a will get deleted.

In this code you return by value and this is where return value optimization comes(RVO) in to the play. a copy of 'a' is created, then origianal 'a' deleted, return copy of 'a'. The correct sequence is not sure.

Upvotes: 3

user4581301
user4581301

Reputation: 33932

The easy part: Does it return "a" by reference or by value?

A find()
{
    ...
    A a;
    return a; 
}

Returns by value.

The hard part: Moreover, does "find" delete "a" first, then return or return first, then delete "a"?

Technically a copy of a is constructed, a is destroyed and the copy is returned. I cannot find anything in the C++ standard that specifies any particular ordering to those operations, but some are logically implied. Obviously you cannot copy after destruction.

I suspect this is left unspecified to allow C++ implementations to support a wide variety of calling conventions.

Note: This means the returned object must be copy-able. If the copy constructor is deleted or inaccessible, you cannot return by value.

There is no way to be certain of whether the return or the destruction is first. It should not matter and if you are designing a program where it does, give your head a shake.

Caveat

However in practice a modern optimizing compiler will do anything in its power to avoid copying and destroying using a variety of approaches under the blanket name of Return Value Optimization.

Note that this is a rare case where the As-If Rule is allowed to be violated. By skipping the copy construction and destruction, some side effects may not take place.

Also note that even if the need to copy is eliminated, the object must still be copy-able.

Sidenote:

A & find()
{
    ...
    A a;
    return a; 
}

will return a reference, but this is a very bad idea. a has Automatic storage duration scoped by the function and will be destroyed on return. This leaves the caller with a dangling reference, a reference to a variable that no longer exists.

To get around this,

std::unique_ptr<A> find()
{
    ...
    auto a = std::make_unique<A>();
    return a; 
}

but you will find that, with a modern compiler, this is no better than returning by value in most cases.

Upvotes: 2

Related Questions