oz10
oz10

Reputation: 158444

const <type>& foo() versus <type> foo()

In a non-template class, is there any reason to prefer function return signatures in the form const <type>& foo(); versus <type> foo();? Where <type> is an intrinsic type. What about if <type> is a class/struct object?

Also interested in whether or not the function being const makes a difference: const <type>& foo() const; to <type> foo() const;

E.g. in a non-template class, non-template function:

const int& foo() const { return member_variable_; }

Versus

int foo() const { return member_variable_; }

Upvotes: 3

Views: 2629

Answers (5)

Jason Govig
Jason Govig

Reputation: 1249

For primitive types, simply return by value. There is no reason to return a primitive by const reference.

For non-primitive types, it depends.

If the value returned is a local variable of the function, then you must return by value. Otherwise, the variable will be destroyed before the caller can consume the returned reference.

If the value returned is a class data member, then you have a choice.

Return by const reference avoids copies, which may be a performance advantage. However, it ties your interface to the implementation, i.e. the data member and return value must be the same type. It is also less safe because the caller can retain the reference longer than the object's lifetime, such as:

const X& x = y->foo();
delete y;
// use x, oops!

Return by value incurs one or two copies, depending on if you can take advantage of return value optimizations (which is likely for simple get() methods such as this). In addition, copies of objects using default copy constructors may be copied more efficiently (think: the compiler can simply memcpy the data).

Recommendation: start with return by value, and switch to return by const reference only after determining that that call/copy is known to be a performance issue.

Finally, another alternative is to return by parameter, which can be useful for more complex objects (e.g., string):

void foo(X& return_val) { return_val = member_variable_; }

or:

void foo(X* return_val) {
    assert(return_val != 0);
    *return_val = member_variable_;
}

Upvotes: 3

Todd Gardner
Todd Gardner

Reputation: 13521

If the type is an intrinsic type, passing around const refs will not improve performance, and may degrade it, as well as being less safe; it is better to prefer passing and returning by value. I am not much of an ASM guy but as I understand it, by reference return means the value couldn't be stored in a register, as it needs an address for the return, and thereby can disable some otherwise useful optimizations; I am not positive on this though.

If it is a class or struct, it depends on lifetime of the value; if it is local to the function then it cannot be returned, otherwise, if it is a class member, I prefer the const type& return as it can offer better performance by avoiding copy-constructors. (opinions differ, as the by value is considered safer). It also saves you from having to implement copy-constructors or using the potentially evil default, which is nice.

Upvotes: 0

Klaim
Klaim

Reputation: 69742

It all depends on what exactly you want to do.

If you want to return a reference to an object to be used by the user code, then :

<type>& foo()  { ... }

If you want to return a reference to an object but in read-only way, allowing only access to const functions of this object type, then:

const <type>& foo() { ... }

If you want to return a reference to an object to be used by the user code, even if the class instance is used in read only (as const) then:

<type>& foo() const { ... }

If you want ot return a reference to an object but in read-only way, allowing only access to const functions of this object type, and event if the class instance is used in read only (as const) then :

const <type>& foo() const { ... }

Just to add a warning : don't return references to function's variables, they are not alive out of the function...

Upvotes: 0

stefanB
stefanB

Reputation: 79830

const <type>& foo();

You might have a resource like container of elements in your class and foo() returns specific element, if you know that the resources will be available long enough you might return const reference to element in container that way you avoid unnecessary allocation/copy of data. It might be const or not, depends on how you deal with the data, if you don't want the data to be modified via the reference returned by foo() then make it const. Maybe you have a case where you want to modify resource and some extra work needs to be done, you would make that non const. You can have both in your api user will choose base on usecase.

<type> foo();

Returns a new copy of resource <type>. That means a copy is made. This is good for simple data or where values might be shared and you want to make sure that each instance of <type> is separate - non-shared like some string or int.

Upvotes: 0

anon
anon

Reputation:

If you need to return a value, you MUST return a value - a const reference is not an acceptable substitute. But I suspect you are asking about something like this:

struct A {
   X x;
    ...
   X f1() { return x; }
   const X & f2() { return x; }
};

I've never come up with a foolproof guideline for this.

Upvotes: 0

Related Questions