[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c++

return type vs passing a reference

Carl Forsman

11/15/2008 8:37:00 PM

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)
20 Answers

Ian Collins

11/15/2008 8:48:00 PM

0

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

Carl Forsman

11/15/2008 9:15:00 PM

0

On Sun, 16 Nov 2008 09:48:02 +1300, Ian Collins <ian-news@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?

Ian Collins

11/15/2008 9:26:00 PM

0

Carl Forsman wrote:
> On Sun, 16 Nov 2008 09:48:02 +1300, Ian Collins <ian-news@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

James Kanze

11/16/2008 12:39:00 AM

0

On Nov 15, 9:48 pm, Ian Collins <ian-n...@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.

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:james.kanze@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

.rhavin grobert

11/16/2008 2:58:00 PM

0

On 15 Nov., 21:37, Carl Forsman <fatwallet...@yahoo.com> wrote:
> 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.

mail.dsp

11/17/2008 5:49:00 AM

0

On Nov 16, 1:37 am, Carl Forsman <fatwallet...@yahoo.com> wrote:
> 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

Ian Collins

11/17/2008 6:21:00 AM

0

mail.dsp@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

Triple-DES

11/17/2008 9:13:00 AM

0

On 17 Nov, 07:20, Ian Collins <ian-n...@hotmail.com> wrote:
> 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.

Ian Collins

11/17/2008 9:23:00 AM

0

Triple-DES wrote:
> On 17 Nov, 07:20, Ian Collins <ian-n...@hotmail.com> wrote:
>> 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

James Kanze

11/17/2008 10:02:00 AM

0

On Nov 16, 3:57 pm, ".rhavin grobert" <cl...@yahoo.de> wrote:
> On 15 Nov., 21:37, Carl Forsman <fatwallet...@yahoo.com> wrote:

> > 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:james.kanze@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