开发者

Is Returning by Reference Useless?

开发者 https://www.devze.com 2023-02-06 14:10 出处:网络
Coming from a C# background, I was more or less puzzled by the seemly weird behavior of returning method handling in C++. My concern now is for a method in C++, returning by reference is not a very us

Coming from a C# background, I was more or less puzzled by the seemly weird behavior of returning method handling in C++. My concern now is for a method in C++, returning by reference is not a very useful technique, this is because-- unlike C#--any variable declared inside a method body will go out of scope once the the control exit the method.

So, in C++, this cannot even compile ( but an equivalent version in C# can):

int& DoubleValue(int nX)
{
    int nValue = nX * 2;
    return nValue; // return a reference to nValue here
} // nValue goes out of scope here

The only time where returning by reference is useful is when you are returning a reference to an existing data member in a class, or you are returning a reference to an element inside a parameter of the method. But in both cases there is really no need to return anything; as the returned reference is already freely available to the caller of the method.

So, my conclusion is, there i开发者_运维技巧s no need to use return by reference at all. Am I right?


Operations like std::vector<>::operator[] return references to elements obtained by dereferencing a pointer (and adding offsets to it). The pointer in that case is a private member internal to the vector, and so not something the user could have obtained themselves without breaking the abstraction of the class.


The only time where returning by reference is useful is when you are returning a reference to an existing data member in a class, or you are returning a reference to an element inside a parameter of the method.

Loosely speaking, true. The variable might not be "owned" by the class (as in tied to its lifetime): it could have been specified to the class by some earlier function call, or a global/singleton known to the class but not part of it, or even a newly allocated area in shared memory or the heap (though returning a reference rather than a pointer suggests the ownership isn't being given to the caller), but ultimately the class must have some access to that data.

But in both cases there is really no need to return anything; as the returned reference is already freely available to the caller of the method.

No, because objects can have private and protected members, and grant friendship to other classes or functions, so it's entirely possible that a called function can access (and hence return a reference to) some data that the caller has no direct access to.

Further, many functions find a specific variable to do some work on, then return a reference to it. If the caller needed to make a separate call to find that variable again, it could be inefficient (as well as verbose in the calling code).

So, my conclusion is, there is no need to use return by reference at all. Am I right?

Nope... due to the flawed premise above.

Another non-necessary but convenient use of return by reference is illustated by typical streaming functions:

std::ostream& operator<<(std::ostream& os, const X& x)
{
    return os << x.str();
}

Above, the reference to means say...

std::cout << x << y;

...is evaluated as...

(std::cout << x) << y;
operator<<(operator<<(std::cout, x), y)

Which all chains together nicely. Similarly:

while (std::cin >> x >> y)
    ...

...works not only due to the chaining for successive inputs to x and y, but also because std::cin is still available for evaluation in a boolean context, which ends up invoking another member function effectively asking whether the streaming operations worked.


It is correct that this doesn't work for returning a reference to something allocated on the stack. That simply can't work.

However returning by reference can still be extremely useful - for example, a collection's indexing operator can return a value by reference, thus enabling you to assign to that element in the collection.


I just wanted to mention that besides returning references to private/protected data members and the chaining of operators, there are techniques in template meta-programming that make use of functions that return-by-reference to temporary variables. This can have a performance gain, but obviously, it needs to be done with care. The Boost.Proto library is one example of expression templates techniques that use references to temporaries to avoid creating temporaries. I'm sorry I cannot really give a simple example of it... I'm not sure I understand it myself, but I just wanted to point out that even the most illogical things in C++ are still allowed, and if they are allowed, someone will find a way to use it wisely. And that includes returning a reference to a temporary.


I hope other experts will come up with more detailed explanation. I just trying to say a few cases when C/C++ programmers use reference types.

The C++ references type is just a syntactic enhancement over the old pointer type of C. In C/C++ all the parameters and return values are value type. That is, values are copied to/from caller/callee. Apparently this is not the desired operation always. So when C/C++ programmers want to prevent unnecessary copying they use pointers or references.

  • To pass large size value
  • To allow caller/callee modify the value

Well.. any other?


The usual purpose of return by reference, is so that chained assignments can be made, like this:

MyVar1 = MyVar2 = Myvar3 = MyVar4;


Try this.

int & DV(int & nX)
{     
     return nX *= 2;     
}
// . . .
int i = 2;
int & j = DV(DV(i));    
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号