By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,651 Members | 1,684 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,651 IT Pros & Developers. It's quick & easy.

return type vs passing a reference

P: n/a
there are 2 ways to return a value from a function
====================
1) passing a reference as parameter - the following will return time

void Table::Get(char* FieldName, *SYSTEMTIME time)
{
_variant_t vtValue;
vtValue = m_Rec->Fields->GetItem(FieldName)->GetValue();

if (vtValue.vt == VT_NULL) {
return NULL;
}
VariantTimeToSystemTimeWithMilliseconds (vtValue.date, time);
}
====================
2) use return keyword
SYSTEMTIME Table::Get(char* FieldName)
{
_variant_t vtValue;
vtValue = m_Rec->Fields->GetItem(FieldName)->GetValue();

if (vtValue.vt == VT_NULL) {
return NULL;
}
SYSTEMTIME m_st;
VariantTimeToSystemTimeWithMilliseconds (vtValue.date, &m_st);
return m_st;
}

====================

Can I only use the 1st way to returning value from a function? as
both ways is doing the same thing to return a value.

Then I can make code more clean to have all function to void return
type and if I need a return value from a function, I just pass in the
pointer that I want the function to return (e.g. *SYSTEMTIME time)
Nov 15 '08 #1
Share this Question
Share on Google+
18 Replies


P: n/a
Carl Forsman wrote:
Then I can make code more clean to have all function to void return
type and if I need a return value from a function, I just pass in the
pointer that I want the function to return (e.g. *SYSTEMTIME time)
You can do this, but I doubt many would agree with your definition of clean.

Doing what you describe is most often used for function templates where
the parameter types are used to resolve the argument types.

Else where, it just leads to clutter. You have to use variables
whenever you call a function, whether you want to retain the result or
not. so rather than simply writing

int n = doSomething();

you end up with

int n;
doSomething( n );

manageable for simple variables, but useless for constants or objects
such as std::auto_ptr that require initialisation.

--
Ian Collins
Nov 15 '08 #2

P: n/a
On Sun, 16 Nov 2008 09:48:02 +1300, Ian Collins <ia******@hotmail.com>
wrote:
>Carl Forsman wrote:
>Then I can make code more clean to have all function to void return
type and if I need a return value from a function, I just pass in the
pointer that I want the function to return (e.g. *SYSTEMTIME time)

You can do this, but I doubt many would agree with your definition of clean.

Doing what you describe is most often used for function templates where
the parameter types are used to resolve the argument types.

Else where, it just leads to clutter. You have to use variables
whenever you call a function, whether you want to retain the result or
not. so rather than simply writing

int n = doSomething();

you end up with

int n;
doSomething( n );

manageable for simple variables, but useless for constants or objects
such as std::auto_ptr that require initialisation.
so you mean I better use Way #2 - (return value) when I want to return
something in a "normal" way?
Nov 15 '08 #3

P: n/a
Carl Forsman wrote:
On Sun, 16 Nov 2008 09:48:02 +1300, Ian Collins <ia******@hotmail.com>
wrote:
>Carl Forsman wrote:
>>Then I can make code more clean to have all function to void return
type and if I need a return value from a function, I just pass in the
pointer that I want the function to return (e.g. *SYSTEMTIME time)
You can do this, but I doubt many would agree with your definition of clean.

Doing what you describe is most often used for function templates where
the parameter types are used to resolve the argument types.

Else where, it just leads to clutter. You have to use variables
whenever you call a function, whether you want to retain the result or
not. so rather than simply writing

int n = doSomething();

you end up with

int n;
doSomething( n );

manageable for simple variables, but useless for constants or objects
such as std::auto_ptr that require initialisation.

so you mean I better use Way #2 - (return value) when I want to return
something in a "normal" way?
With the exception of function templates, yes.

--
Ian Collins
Nov 15 '08 #4

P: n/a
On Nov 15, 9:48*pm, Ian Collins <ian-n...@hotmail.comwrote:
Carl Forsman wrote:
Then I can make code more clean to have all function to void
return type and if I need a return value from a function, I
just pass in the pointer that I want the function to return
(e.g. **SYSTEMTIME time)
You can do this, but I doubt many would agree with your
definition of clean.
Doing what you describe is most often used for function
templates where the parameter types are used to resolve the
argument types.
Was most often used. In modern C++, there are other solutions,
and I think most people would prefer to use a return value, and
specify the return type explicitly, i.e. f< int >(), rather than
f( int& ). (It's also possible to design the function to return
a proxy in which the return type is chosen automatically.)

The most frequent use I've seen for using a reference to return
a value is when the function should return more than one value.
Others occasional uses are when the returned value is a
modification of an object which is also used as an in argument,
and when the return type is very expensive to copy, e.g. an
std::list<with a couple of hundred thousand elements.
Elsewhere, it just leads to clutter. *You have to use
variables whenever you call a function, whether you want to
retain the result or not. *so rather than simply writing
int n = doSomething();
you end up with
int n;
doSomething( n );
manageable for simple variables, but useless for constants or
objects such as std::auto_ptr that require initialisation.
The real problem is when the return type is something that can
be used in further expressions. Which is clearer:
(-b + sqrt( b*b - 4*a*c))/(2*a)
or even
div( add( neg( b ),
sqrt( sub( mul( b, b ), mul( mul( 4, a ), c ) ) ) ),
mul( 2, a ) )
, compared to
BigNumber bSquared ;
mul( &bSquared, b, b ) ;
BigNumber aTimesC ;
mul( &aTimesC, a, c ) ;
BigNumber aTimesCTimes4 ;
mul( &aTimesCTimes4, 4, aTimesC ) ;
BigNumber sum ;
add( &sum, bSquared, aTimesCTimes4 ) ;
BigNumber delta ;
sqrt( &delta, sum ) ;
// ...

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Nov 16 '08 #5

P: n/a
On 15 Nov., 21:37, Carl Forsman <fatwallet...@yahoo.comwrote:
Can I only use the 1st way to returning value from a function? *as
both ways is doing the same thing to return a value.
if you return non-trivial object, some additional ctors/dtros for
temporarily objects may be included. if you have a "filler"-function,
that fill a struct with values for exmpl, you have two ways:

struct X { /* ... */ };
X foo = FillFoo()

and

struct X { /* ... */ };
X foo;
FillFoo(foo);

the second way just uses one struct and needs one construction. the
first way needs a struct inside FillFoo(), sometimes a temporary for
transfer and the foo outside, so you`ll end with 2-3 ctors.

So if you return natives (int, double, ...) or pointers to statics,
use return-type, otherwise use referenced parameters.
Nov 16 '08 #6

P: n/a
On Nov 16, 1:37 am, Carl Forsman <fatwallet...@yahoo.comwrote:
there are 2 ways to return a value from a function
====================
1) passing a reference as parameter - the following will return time

void Table::Get(char* FieldName, *SYSTEMTIME time)
{
_variant_t vtValue;
vtValue = m_Rec->Fields->GetItem(FieldName)->GetValue();

if (vtValue.vt == VT_NULL) {
return NULL;
}
VariantTimeToSystemTimeWithMilliseconds (vtValue.date, time);}

====================
2) use return keyword
SYSTEMTIME Table::Get(char* FieldName)
{
_variant_t vtValue;
vtValue = m_Rec->Fields->GetItem(FieldName)->GetValue();

if (vtValue.vt == VT_NULL) {
return NULL;
}
SYSTEMTIME m_st;
VariantTimeToSystemTimeWithMilliseconds (vtValue.date, &m_st);
return m_st;

}

====================

Can I only use the 1st way to returning value from a function? as
both ways is doing the same thing to return a value.

Then I can make code more clean to have all function to void return
type and if I need a return value from a function, I just pass in the
pointer that I want the function to return (e.g. *SYSTEMTIME time)
If you think the returned object from function may generate any kind
of exception during its construction or assignment and any kind of
memory leak or resource allocation/deallocation misbehave then it
would be better to use reference technique otherwise you can use
return technique. As you can see in STL stack class pop() method
doesn't return anything. You'll have to use top() method to retrieve
top most element of stack.

--
Daya
Nov 17 '08 #7

P: n/a
ma******@gmail.com wrote:
>
If you think the returned object from function may generate any kind
of exception during its construction or assignment and any kind of
memory leak or resource allocation/deallocation misbehave then it
would be better to use reference technique otherwise you can use
return technique.
Why? The exception is still going to have to be caught.

--
Ian Collins
Nov 17 '08 #8

P: n/a
On 17 Nov, 07:20, Ian Collins <ian-n...@hotmail.comwrote:
mail....@gmail.com wrote:
If you think the returned object from function may generate any kind
of exception during its construction or assignment and any kind of
memory leak or resource allocation/deallocation misbehave then it
would be better to use reference technique otherwise you can use
return technique.

Why? *The exception is still going to have to be caught.
I think his point is that if the function is a non-const member
function, and the "return t;" may throw (because T's copy ctor may
throw), the object will not be in the same state as before the
operation, making it impossible to give the strong exception safety
guarantee.
Nov 17 '08 #9

P: n/a
Triple-DES wrote:
On 17 Nov, 07:20, Ian Collins <ian-n...@hotmail.comwrote:
>mail....@gmail.com wrote:
>>If you think the returned object from function may generate any kind
of exception during its construction or assignment and any kind of
memory leak or resource allocation/deallocation misbehave then it
would be better to use reference technique otherwise you can use
return technique.
Why? The exception is still going to have to be caught.

I think his point is that if the function is a non-const member
function, and the "return t;" may throw (because T's copy ctor may
throw), the object will not be in the same state as before the
operation, making it impossible to give the strong exception safety
guarantee.
I can just as easily say that "passing by reference" may throw because
T's assignment operator may throw.

--
Ian Collins
Nov 17 '08 #10

P: n/a
On Nov 16, 3:57 pm, ".rhavin grobert" <cl...@yahoo.dewrote:
On 15 Nov., 21:37, Carl Forsman <fatwallet...@yahoo.comwrote:
Can I only use the 1st way to returning value from a
function? as both ways is doing the same thing to return a
value.
if you return non-trivial object, some additional ctors/dtros
for temporarily objects may be included. if you have a
"filler"-function, that fill a struct with values for exmpl,
you have two ways:

struct X { /* ... */ };
X foo = FillFoo()
and
struct X { /* ... */ };
X foo;
FillFoo(foo);
the second way just uses one struct and needs one
construction.
The second way requires constructing the object before you know
how to initialize it. Depending on the type of object, it may
not be possible (many types don't support default construction),
or it may be overly expensive in runtime (construct the object
with one set of values, then tear it down and construct it with
another).
the first way needs a struct inside FillFoo(), sometimes a
temporary for transfer and the foo outside, so you`ll end with
2-3 ctors.
So if you return natives (int, double, ...) or pointers to
statics, use return-type, otherwise use referenced parameters.
The rule is to use the return value whenever possible. If the
profiler later shows that this does cause a slow down, then you
can change, but you certainly shouldn't worry about it before
it's a problem.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Nov 17 '08 #11

P: n/a
On Nov 17, 6:49 am, mail....@gmail.com wrote:
On Nov 16, 1:37 am, Carl Forsman <fatwallet...@yahoo.comwrote:
[...]
If you think the returned object from function may generate
any kind of exception during its construction or assignment
and any kind of memory leak or resource
allocation/deallocation misbehave then it would be better to
use reference technique otherwise you can use return
technique.
This is simply wrong. If the object is going to leak, it's
going to leak in both cases. (Well designed and implemented
objects don't leak, even if there is an exception.)
As you can see in STL stack class pop() method doesn't return
anything. You'll have to use top() method to retrieve top most
element of stack.
That's a totally different issue. The std::stack<>::pop()
doesn't return anything; the question here is how to return
something. And the justification in the case of pop has nothing
to do with possible resource leaks; it's about maintaining a
strong exception guarantee, in which every action either returns
normally or makes NO change in state. This strong guarantee
isn't really necessary that often, and returning the value via a
reference wouldn't make it any easier to meet.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Nov 17 '08 #12

P: n/a
On Nov 17, 10:12 am, Triple-DES <DenPlettf...@gmail.comwrote:
On 17 Nov, 07:20, Ian Collins <ian-n...@hotmail.comwrote:
mail....@gmail.com wrote:
If you think the returned object from function may
generate any kind of exception during its construction or
assignment and any kind of memory leak or resource
allocation/deallocation misbehave then it would be better
to use reference technique otherwise you can use return
technique.
Why? The exception is still going to have to be caught.
I think his point is that if the function is a non-const
member function, and the "return t;" may throw (because T's
copy ctor may throw), the object will not be in the same state
as before the operation, making it impossible to give the
strong exception safety guarantee.
As a general rule, if the strong exception safety guarantee is
required, mutators shouldn't return anything but return codes.
The strong exception safety guarantee isn't needed that often,
however (or rather, when it is needed, it is generally needed at
a higher level of granularity, for tranactions involving several
objects).

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Nov 17 '08 #13

P: n/a
On Nov 17, 10:22 am, Ian Collins <ian-n...@hotmail.comwrote:
Triple-DES wrote:
On 17 Nov, 07:20, Ian Collins <ian-n...@hotmail.comwrote:
mail....@gmail.com wrote:
>If you think the returned object from function may
generate any kind of exception during its construction or
assignment and any kind of memory leak or resource
allocation/deallocation misbehave then it would be better
to use reference technique otherwise you can use return
technique.
Why? The exception is still going to have to be caught.
I think his point is that if the function is a non-const
member function, and the "return t;" may throw (because T's
copy ctor may throw), the object will not be in the same
state as before the operation, making it impossible to give
the strong exception safety guarantee.
I can just as easily say that "passing by reference" may throw
because T's assignment operator may throw.
Yes, but you could do the assignment before removing the object
from the stack, so you'd still have the strong guarantee.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Nov 17 '08 #14

P: n/a
On 2008-11-17 00:49:17 -0500, ma******@gmail.com said:
>
If you think the returned object from function may generate any kind
of exception during its construction or assignment and any kind of
memory leak or resource allocation/deallocation misbehave then it
would be better to use reference technique otherwise you can use
return technique. As you can see in STL stack class pop() method
doesn't return anything. You'll have to use top() method to retrieve
top most element of stack.
And neither pop() nor top() returns by reference.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Nov 17 '08 #15

P: n/a
James Kanze wrote:
On Nov 15, 9:48 pm, Ian Collins <ian-n...@hotmail.comwrote:
>Carl Forsman wrote:
>>Then I can make code more clean to have all function to void
return type and if I need a return value from a function, I
just pass in the pointer that I want the function to return
(e.g. *SYSTEMTIME time)
>You can do this, but I doubt many would agree with your
definition of clean.
>Doing what you describe is most often used for function
templates where the parameter types are used to resolve the
argument types.

Was most often used. In modern C++, there are other solutions,
and I think most people would prefer to use a return value, and
specify the return type explicitly, i.e. f< int >(), rather than
f( int& ). [...]
Do they? Pity. That means in code like
foo x = bar<foo>();
they'll have to mention the type twice. Usually this
isn't a good idea. Of course, there are cases where
I'd prefer this (if 'foo' is a built-in type that
has no proper default ctor, for example), but
certainly not all the time.
[...]
Schobi
Nov 18 '08 #16

P: n/a
In article <90**********************************@k24g2000pri. googlegroups.com>,
James Kanze <ja*********@gmail.comwrote:
>On Nov 16, 3:57 pm, ".rhavin grobert" <cl...@yahoo.dewrote:
>On 15 Nov., 21:37, Carl Forsman <fatwallet...@yahoo.comwrote:
Can I only use the 1st way to returning value from a
function? as both ways is doing the same thing to return a
value.
>if you return non-trivial object, some additional ctors/dtros
for temporarily objects may be included. if you have a
"filler"-function, that fill a struct with values for exmpl,
you have two ways:

struct X { /* ... */ };
X foo = FillFoo()
>and
>struct X { /* ... */ };
X foo;
FillFoo(foo);
>the second way just uses one struct and needs one
construction.

The second way requires constructing the object before you know
how to initialize it. Depending on the type of object, it may
not be possible (many types don't support default construction),
or it may be overly expensive in runtime (construct the object
with one set of values, then tear it down and construct it with
another).
Indeed, the second way requires an unecessary construction using
invalid values and may then require an assignement or copy inside
FillFoo().
>the first way needs a struct inside FillFoo(), sometimes a
temporary for transfer and the foo outside, so you`ll end with
2-3 ctors.
That is patently incorrect! Please learn what really happens using
any 1/4 decent compiler.:

Try for example the following program:
-------------------------
#include <iostream>

struct Thing
{
Thing() { std::cout << "Thing()\n"; };
Thing(int in): i(in)
{ std::cout << "Thing(int in)\n"; };
Thing(const Thing & rhs ):i(rhs.i)
{ std::cout << "Thing(const Thing &)\n"; };
~Thing() { std::cout << "~Thing()\n"; };
Thing & operator=(const Thing & rhs )
{ i=rhs.i; std::cout << "operator=(const Thing & )\n"; };

int i;
};

void fooFill(Thing & it)
{
it.i = 23;
}
void fooGetFromElsewhere(Thing & it)
{
Thing itLocal(23);
it = itLocal;
}

Thing barFill()
{
Thing itLocal;
itLocal.i = 42;
return itLocal;
}

Thing barGetFromelsewhere()
{
Thing itLocal(42);
return itLocal;
}
int main()
{
{
std::cout << "\nTesting fooFill\n";
Thing it1;
fooFill(it1);
}
{
std::cout << "\nTesting fooGetFromElsewhere\n";
Thing it2;
fooGetFromElsewhere(it2);
}
{
std::cout << "\nTesting barFill\n";
Thing it3 = barFill();
}
{
std::cout << "\nTesting barGetFromelsewhere\n";
Thing it4 = barGetFromelsewhere();
}
return 0;
}
-------------------------------

The worse case scenario is clearly
void fooGetFromElsewhere(Thing & it)
which is a fairly common situation.

There's no difference between as far as number of constructions between
void fooFill(Thing & it)
and
Thing barFill()

But obviously, void fooFill(Thing & it) leads to code obfuscation and
a Thing object that is temporarily initialised to a totally invalid
value.

The best situation is also clearly Thing barGetFromelsewhere() because
nothing is ever initialised to invalid value. Only one Thing object
is ever created and it is created using the correct specific
constructor.
>So if you return natives (int, double, ...) or pointers to
statics, use return-type, otherwise use referenced parameters.
Incorrect rule, please refresh your knowledge base and/or your coding
guidelines.
>The rule is to use the return value whenever possible. If the
profiler later shows that this does cause a slow down, then you
can change, but you certainly shouldn't worry about it before
it's a problem.
Yes. Use return values whenever possible. It makes the code more
readable, it is normally no slower, often faster and in the very rare
cases where it is slower,remedial techniques can then be used for that
particular case.

It is amazing how manay peoples complain about the line:

Thing a = getThing();

Incorrectly assuming that there will be temporary objects created and
copying happening and then recommend:

Thing a; // construct using default constructor
getThing(a);

Ignoring that they are forcing the compiler to produce sub-optimal
code by explicitely constructing an unnecessary default object.

Yannick

For those that don't want to compile: using g++ 4.x the output is:

Testing fooFill
Thing()
~Thing()

Testing fooGetFromElsewhere
Thing()
Thing(int in)
operator=(const Thing & )
~Thing()
~Thing()

Testing barFill
Thing()
~Thing()

Testing barGetFromelsewhere
Thing(int in)
~Thing()

Nov 18 '08 #17

P: n/a
In article <gf**********@hoshi.visyn.net>,
Hendrik Schober <sp******@gmx.dewrote:
>James Kanze wrote:
>>
Was most often used. In modern C++, there are other solutions,
and I think most people would prefer to use a return value, and
specify the return type explicitly, i.e. f< int >(), rather than
f( int& ). [...]

Do they?
Yes
Pity. That means in code like
foo x = bar<foo>();
they'll have to mention the type twice.
I don't see it as a problem. It's compile time. Perfectly safe and
maintainable.
Usually this isn't a good idea.
Is it really a worse idea than calling unecessary default
constructors, creating unecessary copies, having invalidely
default initialised object around?

Personally, I sure prefer:

foo x = bar<foo>();
over
foo x;
bar(x);

And if you need to give the result of bar to someone else:

foo y = func( bar<foo>() );
versus:
foo x;
bar(x);
foo y;
func(y);

I soon loose the will to live.
Of course, there are cases where
I'd prefer this (if 'foo' is a built-in type that
has no proper default ctor, for example), but
certainly not all the time.
IMO, most of the time.

Yannick

Nov 18 '08 #18

P: n/a
Yannick Tremblay wrote:
In article <gf**********@hoshi.visyn.net>,
Hendrik Schober <sp******@gmx.dewrote:
>James Kanze wrote:
>>Was most often used. In modern C++, there are other solutions,
and I think most people would prefer to use a return value, and
specify the return type explicitly, i.e. f< int >(), rather than
f( int& ). [...]
Do they?

Yes
>Pity. That means in code like
foo x = bar<foo>();
they'll have to mention the type twice.

I don't see it as a problem. It's compile time. Perfectly safe and
maintainable.
Until someone changes the above code to

foo x = bar<blrgl>();

while there's a possible, but unwanted conversion from
'blrgl' too 'foo'.
> Usually this isn't a good idea.

Is it really a worse idea than calling unecessary default
constructors, creating unecessary copies, having invalidely
default initialised object around?
Not always. But often enough to not to want me have this
as a hard rule.
[...]
Yannick
Schobi
Nov 18 '08 #19

This discussion thread is closed

Replies have been disabled for this discussion.