C ++ References and Return Values

I came across the following code:

class MyClass { // various stuff including ... double *myarray; double &operator() (const int n){ return myarray[n]; } double operator() (const int n) const { return myarray[n]; } // various other stuff ... } 

So, what is the practical difference in the two overloads of "()"? I mean, I know: "The first returns a double reference, and the second returns a double", but what does this mean in practice? When will I use one, and when will I use another? The second (double return) seems pretty safe and straightforward. Is the first ever dangerous in some way?

+5
source share
4 answers

They differ in that the first allows you to change the element of the array, and the second returns a value, so you can:

c: double & operator ()

 MyClass mm; mm(1) = 12; 

but also:

 std::cout << mm(1); 

c: double operator ()

 // mm(1) = 12; // this does not compile std::cout << mm(1); // this is ok 

Also, when returning a link, it is more often used when using operator[] , for example, when using std::vector::operator[] .

by the way. its common for two versions of operator() is one constant and the second non-constant. The Const version will be called for const objects, and the second for non const. But usually their signature:

 double& operator() (const int n); const double& operator() (const int n) const; 
+6
source

In general, the difference between pointers and references is that pointers can be changed and can also point to nullptr , i.e. to nothing. Links are fixed.

In this example, the operator () operator does not return the link, but copies the value, that is, changes the resulting value in this way, does not change the double in the class.

If he really returned double &, you could use both of these methods interchangeably (of course, with different notation in use), and proposing both would be just a convenience for the user of this class.

+4
source

What does this mean in practice?

This means that the second method returns by value, i.e. makes a copy of the array element / double and returns that copy to the caller. The first method returns a by-reference, i.e. It does not make a copy of the double, but rather returns a link to the source / binary location, which the calling code can then use to directly access the internal, double array if it wants. (if this helps, the semantics of the indirectness of the returned link are somewhat similar to the semantics of the pointer, with the exception of the syntax, which is more like the traditional C / C ++ function function)

When will I use one, and when will I use another?

The by-value method is safer because the probability of using undefined is less; the backlink method gives you additional flexibility (i.e., the caller can then update the element in the array, writing down the link it received as the return value), and in some situations it can be more efficient (for example, returning the link avoids having to copy the object, which can be an expensive operation if the object is large or complex). For a small object such as double, returning by value is probably more efficient than returning by reference.

How dangerous is [link method]?

This could be, for example, if you must return a reference to an automatic / stack variable, which will lead to undefined behavior, since the variable will be destroyed before the call code can use it:

 double & dont_ever_do_this() { double x = 5.0; // x will be destroyed as this method returns! return x; // so returning a reference to x is a silly thing to do } 

Similarly, in your MyClass example, if the caller holds onto the returned link and then tries to use it after deleting myarray, the caller will read (or write) a memory location that is no longer valid, and this will result in undefined behavior (read: Bad Things).

And, of course, returning a non-constant reference means that the caller has the ability to change the contents of the returned element of the array, even if your class does not know about it, which may not be what you want to allow.

+4
source

You can see the categories of values ​​at this link. http://en.cppreference.com/w/cpp/language/value_category

In the double& operator() case, you have an lvalue expression and can use it as an lvalue (for assignment, printing, etc.)

 MyClass class; class(7) = 21; 

or

 std::cout << class(7); 

And in the case of double operator() const , you have an rvalue expression. In this case, you can also use it with a const object.

+2
source

All Articles