Sign in to follow this  
Tom Backton

Function Return Type (C++)

Recommended Posts

This question is probably a general C++ question, but I'm asking here because maybe the context matters. I have a color class. And there is a function that sets the active color. The return type can be const Color* , const Color& or color. Right now there are tow versions for the first two options. Classes can be big, so generally returning an object by value should be avoided if possible. In this case the size is 12 bytes. So returning by reference and by address cover the cases of dynamically-allocated and statically-allocated objects without the need to type * or &. Return by value may be needed only is the color is supplied as an object returned by value by a function. The question is whether this ever happens. Are the first two options enough? I want to be sure...so I'm asking you experienced guys...

Share this post


Link to post
Share on other sites
There are a few ways to do it, but my preference is to take a reference as an argument. That way the programmer is responsible for both allocating and freeing the color class.

However, if we're talking about an RGB triplet, then returning a value isn't going to break anything.

Share this post


Link to post
Share on other sites
Quote:
Original post by Tom Backton
Classes can be big, so generally returning an object by value should be avoided if possible. In this case the size is 12 bytes.


Don't optimize the small things until you know they're a bottleneck. Worry about big-O complexity of algorithms first.

Quote:
Return by value may be needed only is the color is supplied as an object returned by value by a function.


Or when the function creates the color out of thin air, and you don't want to dynamically allocate it (because that requires the caller to deallocate memory that wasn't allocated there, adds extra memory burden for the pointer itself, and may slow things down anyway for the dynamic allocation).

Besides which, the compiler can quite often optimize out the copying that you'd expect to happen with return-by-value. Especially if the function call gets inlined.

Share this post


Link to post
Share on other sites
The choice of whether to return a value or a reference is irrelevant to the size of the object, and even irrelevant to the cost to copy or move it.
Indeed, that cost can be nullified at will, and copies/moves won't happen unless they're needed anyway.

To choose correctly, you should think in terms of lifetimes, rather.

Share this post


Link to post
Share on other sites
Quote:
Original post by loufoque
The choice of whether to return a value or a reference is irrelevant to the size of the object, and even irrelevant to the cost to copy or move it.
Indeed, that cost can be nullified at will, and copies/moves won't happen unless they're needed anyway.

To choose correctly, you should think in terms of lifetimes, rather.


See, you say that, but then the lead guy on the DS or the PSP will get pretty mad at you.

Pragmatic advice: If it's greater than the machine word, and possible, const-reference it.

Share this post


Link to post
Share on other sites
Quote:
Original post by _goat
Quote:
Original post by loufoque
The choice of whether to return a value or a reference is irrelevant to the size of the object, and even irrelevant to the cost to copy or move it.
Indeed, that cost can be nullified at will, and copies/moves won't happen unless they're needed anyway.

To choose correctly, you should think in terms of lifetimes, rather.


See, you say that, but then the lead guy on the DS or the PSP will get pretty mad at you.

Pragmatic advice: If it's greater than the machine word, and possible, const-reference it.


Even on the DS and PSP, you don't want to optimize unless necessary.

Share this post


Link to post
Share on other sites
Quote:
Original post by CRACK123
Quote:
Original post by _goat
Quote:
Original post by loufoque
The choice of whether to return a value or a reference is irrelevant to the size of the object, and even irrelevant to the cost to copy or move it.
Indeed, that cost can be nullified at will, and copies/moves won't happen unless they're needed anyway.

To choose correctly, you should think in terms of lifetimes, rather.


See, you say that, but then the lead guy on the DS or the PSP will get pretty mad at you.

Pragmatic advice: If it's greater than the machine word, and possible, const-reference it.


Even on the DS and PSP, you don't want to optimize unless necessary.


But passing parameters and data by const reference doesn't cost you anything besides a few extra characters. It's the same reason why you should prefer ++i instead of i++ when they're logically equivalent. The cost is nothing or very little, but there are potential gains.

So when I have a function that takes parameters larger than 1 or 2 words, I make them const reference. Same for a function return type if I don't actually need a copy.

Share this post


Link to post
Share on other sites
Quote:
Original post by Sc4Freak
Quote:
Original post by CRACK123
Quote:
Original post by _goat
Quote:
Original post by loufoque
The choice of whether to return a value or a reference is irrelevant to the size of the object, and even irrelevant to the cost to copy or move it.
Indeed, that cost can be nullified at will, and copies/moves won't happen unless they're needed anyway.

To choose correctly, you should think in terms of lifetimes, rather.


See, you say that, but then the lead guy on the DS or the PSP will get pretty mad at you.

Pragmatic advice: If it's greater than the machine word, and possible, const-reference it.


Even on the DS and PSP, you don't want to optimize unless necessary.


But passing parameters and data by const reference doesn't cost you anything besides a few extra characters. It's the same reason why you should prefer ++i instead of i++ when they're logically equivalent. The cost is nothing or very little, but there are potential gains.

So when I have a function that takes parameters larger than 1 or 2 words, I make them const reference. Same for a function return type if I don't actually need a copy.



True there are potential gains and I don't disagree there at all but largely when you hit performance issues normally there are probably other reasons/factors than const referencing something. Not that I would say not to return a const reference and by practice most of us end of doing that before even getting into the performance optimization part.

Share this post


Link to post
Share on other sites
Quote:
Original post by Sc4Freak
But passing parameters and data by const reference doesn't cost you anything besides a few extra characters. It's the same reason why you should prefer ++i instead of i++ when they're logically equivalent. The cost is nothing or very little, but there are potential gains.

So when I have a function that takes parameters larger than 1 or 2 words, I make them const reference. Same for a function return type if I don't actually need a copy.


There's a big difference between passing objects by const reference, and transforming a function that returns an object by value into one that modifies a non-const reference "out parameter", which is the technique that was actually being discussed.

Share this post


Link to post
Share on other sites
Quote:
Original post by CRACK123
Even on the DS and PSP, you don't want to optimize unless necessary.


Sure. It's necessary from the very first line. Only a company destined to fail would start writing code as if all platforms behaved like the PC and that BigO optimisation would be 80% of the optimisations and small stuff like references would be the other 20%. It takes time and money to convert return signatures/arguments to references (const or otherwise) whilst being sure you haven't introduced any bugs. It's not trivial. It's especially non-trivial when you learn just how weak the DS's computational powers are. You want so few copies of objects it ain't funny. You may think that it's easy to convert stuff with an IDE, it's not. Currently, we have a string class that has an implicit cast to TChar*. We can't remove it, because the amount of time it would take to get the code working isn't worth it. A const reference is future-proof and, if used as a habit, probably might not enter your brain as a pre-optimisation (it doesn't to mine).

Quote:
Original post by Zahlman
Quote:
Original post by Sc4Freak
But passing parameters and data by const reference doesn't cost you anything besides a few extra characters. It's the same reason why you should prefer ++i instead of i++ when they're logically equivalent. The cost is nothing or very little, but there are potential gains.

So when I have a function that takes parameters larger than 1 or 2 words, I make them const reference. Same for a function return type if I don't actually need a copy.


There's a big difference between passing objects by const reference, and transforming a function that returns an object by value into one that modifies a non-const reference "out parameter", which is the technique that was actually being discussed.


I thought he was talking about const-reference objects? That's what I can make out from his post.

Share this post


Link to post
Share on other sites
I'm talking of returning a value vs returning a reference, pointer, or const reference.

The solution is simple:
1) Never return a pointer, that's just unclear resource management. I would even say to ban pointers and never use them.
2) Return a reference only if the returned object outlives the scope of the function. That much is obvious, of course, because doing it any other way would lead to undefined behaviour. Also, the callee should *not* be responsible for freeing the memory. The reference just references some other variable that will be automatically freed according to the function semantics. The obvious example is a member function that returns a reference to a member variable.
3) Otherwise return a value.

The choice is about semantics and ownership, not about efficiency.

Share this post


Link to post
Share on other sites
Quote:
Original post by _goat
Quote:
Original post by Zahlman
Quote:
Original post by Sc4Freak
But passing parameters and data by const reference doesn't cost you anything besides a few extra characters. It's the same reason why you should prefer ++i instead of i++ when they're logically equivalent. The cost is nothing or very little, but there are potential gains.

So when I have a function that takes parameters larger than 1 or 2 words, I make them const reference. Same for a function return type if I don't actually need a copy.


There's a big difference between passing objects by const reference, and transforming a function that returns an object by value into one that modifies a non-const reference "out parameter", which is the technique that was actually being discussed.


I thought he was talking about const-reference objects? That's what I can make out from his post.


I was referring to:

Quote:
Original post by erissian
There are a few ways to do it, but my preference is to take a reference as an argument. That way the programmer is responsible for both allocating and freeing the color class.


... without which, there would have been not nearly so much to discuss. :)

Share this post


Link to post
Share on other sites
Correct me if I'm wrong, but I can't see where the OP stated he was programming in a resource constrained environment. I don't see the point in thinking like a DS or PSP programmer unless one is developing for such a limited system.

Share this post


Link to post
Share on other sites
If the color you return is stored within your color class, than the best way to return 'const Color&'. Otherwise you should return 'color', i.e by value. In any case it is better to define your function as inline. So if it is your internal function within your application (and not a library api function), 'by value' will be optimized by the compiler.

And it is always a good idea to have the basic frequently used functions as fast as possible.

Share this post


Link to post
Share on other sites
... Actually, as far as I can tell, this is a general programming question. Moved.

Quote:
Original post by DonnieZM
If the color you return is stored within your color class, than the best way to return 'const Color&'. Otherwise you should return 'color', i.e by value. In any case it is better to define your function as inline. So if it is your internal function within your application (and not a library api function), 'by value' will be optimized by the compiler.

And it is always a good idea to have the basic frequently used functions as fast as possible.


'inline' is almost as useless as 'register' these days; today's compilers basically inline whatever they damn well please. (You can use __forceinline with MSVC, and probably something similar with GCC, but why wouldn't you want to let the compiler decide?)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this