Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Return value, reference, const reference

Can you explain to me the difference between returning value, reference to value, and const reference to value?

Value:

Vector2D operator += (const Vector2D& vector) {     this->x += vector.x;     this->y += vector.y;     return *this; } 

Not-const reference:

Vector2D& operator += (const Vector2D& vector) {     this->x += vector.x;     this->y += vector.y;     return *this; } 

Const reference:

const Vector2D& operator += (const Vector2D& vector) {     this->x += vector.x;     this->y += vector.y;     return *this; } 

What is the benefit of this? I understand the sense behind const reference passing to function as you want to make sure not to modify this value on which reference is pointing to inside a the function. But I'm confused by the meaning of returning const reference. Why returning of reference is better than returning of value, and why returning of const reference is better than returning of not-const reference?

like image 486
Majak Avatar asked Feb 14 '14 11:02

Majak


People also ask

How do I return references to const?

You want to return a const reference when you return a property of an object, that you want not to be modified out-side of it. For example: when your object has a name, you can make following method const std::string& get_name(){ return name; }; . Which is most optimal way.

Can return type be const?

(C++) const return typeThe value of a return type that is declared const cannot be changed. This is especially useful when giving a reference to a class's internals (see example #0), but can also prevent rarer errors (see example #1). Use const whenever possible [1-7].

Can references be const?

The grammar doesn't allow you to declare a “const reference” because a reference is inherently const . Once you bind a reference to refer to an object, you cannot bind it to refer to a different object.

Does const reference make a copy?

Not just a copy; it is also a const copy. So you cannot modify it, invoke any non-const members from it, or pass it as a non-const parameter to any function. If you want a modifiable copy, lose the const decl on protos .


2 Answers

There is no difference unless you write something weird like

(v1 += v2) = v3; 

In the first case, the assignment will be to a temporary, and the overall effect will be v1 += v2.

In the second case, the assignment will be to v1, so the overall effect will be v1 = v3.

In the third case, the assignment won't be allowed. This is probably the best option, since such weirdness is almost certainly a mistake.

Why returning of reference is better than returning of value?

It's potentially more efficient: you don't have to make a copy of the object.

and why returning of const reference is better than returning of not-const reference?

You prevent weirdness like the above example, while still allowing less weird chaining such as

v1 = (v2 += v3); 

But, as noted in the comments, it means that your type doesn't support the same forms of (ab)use as the built-in types, which some people consider desirable.

like image 153
Mike Seymour Avatar answered Sep 20 '22 01:09

Mike Seymour


Value:

Returning by value means that you are returning a copy of an object. This puts requirements on the class (it has to be copyable or moveable). This means that for object of some classes returning by value may be expensive (in a case where RVO or NRVO does not work or is switched off). This also means that the new object is independent (subject to its design) from other objects and is a value of its own. This is what you probably should return from many binary operators like +, -, * and so on.

Non-const reference:

You really return an alias for another object. The alias being non const allow you to modify aliased object. This is what you should return from some unary oprators like prefix ++ and --, and * (dereference) as you usually want to have the ability to modify returned object.

This is returned by operator>> and operator<< overloaded for streams. This allows chaining of operators:

cout << 5 << "is greater then" << 1 << endl; cin >> myInt >> myFloat; 

You can also return reference to *this when you want to allow chaining of regular methods like this:

object.run().printLastRunStatistics(); 

Const reference:

Like above but you CANNOT modify aliased object. May be used instead of returning by value when the object to be returned is expensive to copy and when you can ensure its existence after you return from a function.

This is what operator= usually returns to allow multiple assignments in a way standard types support them:

a = b = c; 

Const-reference used in operator= prevents this kind of usage (not supported by standard type as far as I remember):

++(a = b); 

which would be allowed if normal reference was used.

like image 36
Tomek Avatar answered Sep 21 '22 01:09

Tomek