473,385 Members | 1,740 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Returning by value, returning by reference

When I compile and run the following on my system:
#include <iostream>

static int hello = 78;
int ReturnValue(void)
{
return hello;
}
int& ReturnRef(void)
{
return hello;
}
int main(void)
{
const int& value = ReturnValue();

const int& ref = ReturnRef();

if ( &value == &ref )
{
std::cout << "They're the same!!" << std::endl;
}
else
{
std::cout << "They're different!!" << std::endl;
}

std::system("pause");

}
, it prints "They're different". I'm curious as to why?!
I was thinking along these lines at first:

You can bind a temporary returned from a function to a reference. Therefore,
it's just the same as the function returning by reference, except that it's
const.

As such, I expected the output to be "They're the same!!".
Any thoughts?
-JKop
Jul 22 '05 #1
19 1933
JKop posted:
When I compile and run the following on my system:
#include <iostream>

static int hello = 78;
int ReturnValue(void)
{
return hello;
}
int& ReturnRef(void)
{
return hello;
}
int main(void)
{
const int& value = ReturnValue();

const int& ref = ReturnRef();

if ( &value == &ref )
{
std::cout << "They're the same!!" << std::endl;
}
else
{
std::cout << "They're different!!" << std::endl;
}

std::system("pause");

}
, it prints "They're different". I'm curious as to why?!
I was thinking along these lines at first:

You can bind a temporary returned from a function to a reference.
Therefore, it's just the same as the function returning by reference,
except that it's const.

As such, I expected the output to be "They're the same!!".
Any thoughts?
-JKop

Another thought:

A function that returns a const reference.
A function that returns by value.
int Monkey(void)
{
int monkey = 72;

return monkey;
}
const int& Ape(void)
{
int ape = 72;

return ape;
}
They're exactly the same, right? There shouldn't be any difference, eg. an
extra temporary made.
-JKop
Jul 22 '05 #2
"JKop" <NU**@NULL.NULL> wrote in message
news:6q*****************@news.indigo.ie...
....
const int& value = ReturnValue(); .... You can bind a temporary returned from a function to a reference. Therefore, it's just the same as the function returning by reference, except that it's const.

Not the same actually.
The story is more like: the function returned the copy of a value,
eventually stored on the stack. By using a const reference, we are
trying to tell the compiler to avoid copying the value again into
a local variable, and to extend the lifetime of the temporary it
stores a reference to.

The original variable whose copy was returned by "ReturnValue()"
is never accessible from the outside.
hth
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- e-mail contact form
Brainbench MVP for C++ <> http://www.brainbench.com
Jul 22 '05 #3
JKop wrote in news:6q*****************@news.indigo.ie in comp.lang.c++:
When I compile and run the following on my system:
#include <iostream>

static int hello = 78;
int ReturnValue(void)
{
This Function returns a *copy* of 'hello'.
return hello;
}
int& ReturnRef(void)
{
return hello;
}
int main(void)
{
const int& value = ReturnValue();
In the above the compiler creates a temporary in which it stores
a the value returned by ReturnValue. In effect something like:

int temp = ReturnValue();
int const &value = temp;

const int& ref = ReturnRef();

if ( &value == &ref )
{
std::cout << "They're the same!!" << std::endl;
}
else
{
std::cout << "They're different!!" << std::endl;
}

std::system("pause");

}
, it prints "They're different". I'm curious as to why?!
I was thinking along these lines at first:

You can bind a temporary returned from a function to a reference.
This is true, but you conclusion doesen't follow.
Therefore, it's just the same as the function returning by reference,
except that it's const.

Binding temporaries to constant references *isn't* a result
of the way temoraries are created, it happens because the
standard says so, there is hence no "Therefore".
As such, I expected the output to be "They're the same!!".
Any thoughts?


Logic applies to why the language is the way it is, but that
doesn't mean the language is (always) logical.

If you haven't got one already get a good book.
If you haven't got it already get a copy of the C++ Standard.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #4
JKop wrote in news:5u*****************@news.indigo.ie in comp.lang.c++:

A function that returns a const reference.
A function that returns by value.
This is OK.
int Monkey(void)
{
int monkey = 72;

return monkey;
}

This is UB (it maybe diagnostic (i.e. warning) required).

const int& Ape(void)
{
int ape = 72;

return ape;
'ape' has now been destroyed, the returned reference, referes
to an object that no longer exists.

}
They're exactly the same, right? There shouldn't be any difference,
eg. an extra temporary made.


No.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #5
Rob Williscroft posted:
Therefore, it's just the same as the function returning by reference,
except that it's const.


Binding temporaries to constant references *isn't* a result
of the way temoraries are created, it happens because the
standard says so, there is hence no "Therefore".


I'll make myself more clear:
int monkey(void);

const int& ape(void);
I wasn't talking about how you've to:

const int& primate = monkey;
-JKop
Jul 22 '05 #6

int monkey = ReturnIntValue();

const int& monkey = ReturnIntValue();
I once heard an argument that the binding-to-a-reference one is better
because it avoids an extra temporary. If this is so, why the hell doesn't
the following print "They're the same!!"?:

#include <iostream>

const int* g_p1;

const int* g_p2;
int Chocolate(void)
{
int monkey = 42;

g_p1 = &monkey;
return monkey;
}
int main(void)
{
const int& cream = Chocolate();

g_p2 = &cream;

if (g_p1 == g_p2)
{
std::cout << "They're the same!!";
}
{
std::cout << "They're different!!";
}

std::system("pause");

}
-JKop

Jul 22 '05 #7
JKop wrote in news:JK*****************@news.indigo.ie in comp.lang.c++:
Rob Williscroft posted:
Therefore, it's just the same as the function returning by reference,
except that it's const.


Binding temporaries to constant references *isn't* a result
of the way temoraries are created, it happens because the
standard says so, there is hence no "Therefore".


I'll make myself more clear:
int monkey(void);

const int& ape(void);
I wasn't talking about how you've to:

const int& primate = monkey;


That *isn't* clearer in any way.
Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #8
Rob Williscroft posted:
JKop wrote in news:5u*****************@news.indigo.ie in comp.lang.c++:

A function that returns a const reference.
A function that returns by value.

This is OK.

int Monkey(void)
{
int monkey = 72;

return monkey; }


This is UB (it maybe diagnostic (i.e. warning) required).


What does UB stand for?

While I'm asking, what does OP stand for?


const int& Ape(void)
{
int ape = 72;

return ape;


'ape' has now been destroyed, the returned reference, referes
to an object that no longer exists.

When you return by value, the object exists until the next ;. When you
return by reference, the object is destroy immediately. Is that what you're
saying? ie.

int ReturnIntValue(void);

const int& ReturnIntRef(void);

void TakesInt(const int);
int main(void)
{
TakesInt( ReturnIntValue() );

//Nothing wrong because the object exists until the next ;

TakesInt( ReturnIntRef() );

//This is undefined behaviour because the object was destroyed
//immediately

}
I don't know why I'm asking the following question, but still absolute
clarity would be nice:

const int ReturnValue(void);
int ReturnValue(void);
They're exactly the same, right? (Yes, I realize how stupid the question
sounds!)

-JKop
Jul 22 '05 #9
Rob Williscroft posted:
JKop wrote in news:JK*****************@news.indigo.ie in comp.lang.c++:
Rob Williscroft posted:
Therefore, it's just the same as the function returning by reference,
except that it's const.
Binding temporaries to constant references *isn't* a result
of the way temoraries are created, it happens because the
standard says so, there is hence no "Therefore".


I'll make myself more clear:
int monkey(void);

const int& ape(void);
I wasn't talking about how you've to:

const int& primate = monkey;


That *isn't* clearer in any way.
Rob.


Anyway, this has been addressed elsewhere in the thread.

END

-JKop
Jul 22 '05 #10
Rob Williscroft wrote:


const int& Ape(void)
{
int ape = 72;

return ape;


'ape' has now been destroyed, the returned reference, referes
to an object that no longer exists.


Indeed. Looks like an example for Item 23 in from Scott Meyers' book
"Effective C++": "Don't try to return a reference when you must return an
object".

--
Chris Gordon-Smith
London
Homepage: http://graffiti.virgin.net/c.gordon-smith/
Email Address: Please see my Home Page
Jul 22 '05 #11
JKop wrote in news:KV*****************@news.indigo.ie in comp.lang.c++:
Rob Williscroft posted:
JKop wrote in news:5u*****************@news.indigo.ie in
comp.lang.c++: [snip]

int Monkey(void)
{
int monkey = 72;

return monkey; }

This is UB (it maybe diagnostic (i.e. warning) required).


What does UB stand for?


Udefined Behaviour, its whaen the Standard gives up and nolonger
determines what behaviour if any your program exhibits.
While I'm asking, what does OP stand for?
Original Poster, the person that started the thread.


const int& Ape(void)
{
int ape = 72;

return ape;
'ape' has now been destroyed, the returned reference, referes
to an object that no longer exists.

When you return by value, the object exists until the next ;


No when you return by value a *copy* is made snd is passed back to the
caller. In the case of int's this is usally done in a CPU register.
In the case of objects to big for a register this is usually done
by havving the caller create a temporary before making the call
and passing (in some way) the address (a pointer to) of the
temorary.

When you
return by reference, the object is destroy immediately. Is that what
you're saying? ie.


Its not to do with returning by reference, in your example 'ape' is
an automatic variable and is destroyed when the block (in this case
the body {} of the fuction 'Ape()') it was created in is left ( the
reurn statment ).

[snip]

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #12
Rob Williscroft posted:
int Monkey(void)
{
int monkey = 72;

return monkey; }

Undefined behaviour???????????????????????????????????
-JKop
Jul 22 '05 #13
JKop posted:

int monkey = ReturnIntValue();

const int& monkey = ReturnIntValue();

Well there's one extra temporary staring me in the face!
Dropped the ball on that one.

With the first one, there's 3 objects. Firstly, there's the int variable
within the function ReturnIntValue. Then there's the temporary returned.
Then there's my monkey variable in main.
With the second, there's 2 objects. Firstly, there's the int variable within
the function ReturnIntValue. Then there's the temporary returned. THIS IS
WHERE IT'S DIFFERENT: I don't create a new variable and copy it over, I hang
on to the temporary.
Which begs the question...

Why must there be a temporary? Why can't it just return the variable from
within the function.
-JKop
Jul 22 '05 #14
JKop posted:
Rob Williscroft posted:
int Monkey(void)
{
int monkey = 72;

return monkey; }

Undefined behaviour???????????????????????????????????
-JKop


Opps I just realized that you were referring to the code that *followed*,
rather than preceeded.

I've gotten the moral of the story here:

int Monkey(void)
{
int monkey = 72;

return monkey;
}
The monkey object gets destroyed straight away even before the function
returns, but a copy is made of it before it's destroyed, this is the
temporary passed to the calling function. This temporary lasts until the
next ; in the calling function, unless it's bound to a reference, as so:

int main(void)
{
const int& monkey = Monkey();
}
In which case, the temporary lasts as long as would an automatic variable if
it were declared in the place of monkey.

-JKop
Jul 22 '05 #15
JKop wrote in news:1F*****************@news.indigo.ie in comp.lang.c++:

Opps I just realized that you were referring to the code that
*followed*, rather than preceeded.
Sorry about that I over quoted.

I've gotten the moral of the story here:

int Monkey(void)
{
int monkey = 72;

return monkey;
}
The monkey object gets destroyed straight away even before the
function returns, but a copy is made of it before it's destroyed, this
is the temporary passed to the calling function. This temporary lasts
until the next ; in the calling function, unless it's bound to a
reference, as so:

int main(void)
{
const int& monkey = Monkey();
}
In which case, the temporary lasts as long as would an automatic
variable if it were declared in the place of monkey.


Yep.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #16
JKop <NU**@NULL.NULL> wrote in message news:<FO*****************@news.indigo.ie>...
int monkey = ReturnIntValue();

const int& monkey = ReturnIntValue();
I once heard an argument that the binding-to-a-reference one is better
because it avoids an extra temporary. If this is so, why the hell doesn't
the following print "They're the same!!"?:

#include <iostream>

const int* g_p1;

const int* g_p2;
int Chocolate(void)
{
int monkey = 42;

g_p1 = &monkey;
return monkey;
}
int main(void)
{
const int& cream = Chocolate();

g_p2 = &cream;

if (g_p1 == g_p2)
{
std::cout << "They're the same!!";
}
{
std::cout << "They're different!!";
}

std::system("pause");

}
-JKop

Well, many things at work here.

(1) If you want to return by reference, that has to be
explicitly mentioned in the method prototype. So the
chocolate method should have signature as follows:

int &chocolate(void)

(2) You can not return by reference a local variable, in
your case, monkey is a local variable in chocolate
method. SO it should be made global. As a side remark,
the pointer g_p1 will become dangling because monkey
variable will be destroyed once control comes out of
chocolate method.

(3) There is no matching-else to the if statement in the
main(). Also because of the way standard I/O does
buffering, a cout may not result in immediate display
of the string "They are same!" or whatever, put an
endl at the end of cout: cout<<"string"<<endl;

--BG.
Jul 22 '05 #17
> JKop <NU**@NULL.NULL> wrote in message
news:<FO*****************@news.indigo.ie>...
int monkey = ReturnIntValue();

const int& monkey = ReturnIntValue();
I once heard an argument that the binding-to-a-reference one is better
because it avoids an extra temporary. If this is so, why the hell doesn't the following print "They're the same!!"?:

#include <iostream>

const int* g_p1;

const int* g_p2;
int Chocolate(void)
{
int monkey = 42;

g_p1 = &monkey;
return monkey;
}
int main(void)
{
const int& cream = Chocolate();

g_p2 = &cream;

if (g_p1 == g_p2)
{
std::cout << "They're the same!!";
}
{
std::cout << "They're different!!";
}

std::system("pause");

}
-JKop

<<big snip>>
Is this issue still live? Anyway, response to JKop...

g_p1 contains the address of the local variable monkey, which has gone out
of scope when Chocolate returns to main. It may or may not be useable, but
certainly isn't valid, unless you like to program with undefined behaviour.
g_p2 contains the address of the temporary copy of monkey which is being
held because it was returned with the reference cream.
The two variables (the original monkey, now out of scope, and the copy of
monkey held with the reference cream) are in different places. Therefore
g_p1 and g_p2 are different.
Taking the address of a reference to a temporary seems a little bit dicey to
me --- and may well be UB.
--
Gary
Jul 22 '05 #18
JKop wrote:
When I compile and run the following on my system:
#include <iostream>

static int hello = 78;
int ReturnValue(void)
{
return hello;
}
int& ReturnRef(void)
{
return hello;
}
int main(void)
{
const int& value = ReturnValue();

This creates a temporary, and binds 'value' to it.
const int& ref = ReturnRef();

This bind 'ref' to the global variable 'hello'. if ( &value == &ref )
Using the addressof operator on references gives you the address of the
object they reference. Therefore '&value' is the address of the
temporary, and '&ref' is the address of 'hello'.

Change this to 'if (&ref == &hello)' and they should be the same. {
std::cout << "They're the same!!" << std::endl;
}
else
{
std::cout << "They're different!!" << std::endl;
}

std::system("pause");

}
, it prints "They're different". I'm curious as to why?!

Alan
Jul 22 '05 #19
"JKop" <NU**@NULL.NULL> wrote in message
news:Vz*****************@news.indigo.ie...
Why must there be a temporary? Why can't it just return the
variable from within the function.

When you return a (non-static) local variable, the compiler
is allowed to make the local variable and the return-value
temporary the same.
This is called the NRVO (Named Return Value Optimization),
which some compilers do implement.

Try:

#include <iostream>

class Value
{
public:
int m;
Value(int i) : m(i) {}
Value(const Value& o) : m(o.m) { std::cout<<"Value Copied\n"; }
};

Value f()
{
Value v(5);
return v; // return may require copying
}

int main()
{
Value mine = f(); // var init may require copying
return 0;
}

Depending on how smart your compiler is, the previous program
may output "Value Copied" 0 to 2 times.
Things that may help less 'advanced' compiler optimize-out
the copies are to:
- rewrite f()'s body as:
return Value(5);
( Optimizing this out is called RVO (Return Value Optimization)
and is more commonly supported than NRVO ).
- change the type of mine() to a const-reference:
Value const& mine = f();
This may help some compilers optimize-out a copy.
hth -Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- e-mail contact form
Brainbench MVP for C++ <> http://www.brainbench.com
Jul 22 '05 #20

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
by: Krackers | last post by:
How do you write a function which returns a reference to an array. I can only get a function to return a copy of the array itself. I've had a look at some other threads in this group an the return...
9
by: mjm | last post by:
Folks, Stroustrup indicates that returning by value can be faster than returning by reference but gives no details as to the size of the returned object up to which this holds. My question is...
4
by: Patrick | last post by:
I want to achieve the following behaviour but I am having trouble getting there...bare with me im knew to c++ , so its probably rather trivial! To have a class ClassA, and composed within this...
18
by: cppaddict | last post by:
Hi, Is it considered bad form to have the subscript operator return a const reference variable? If not, what is the proper way to do it? My question was prompted by the code below, my...
11
by: JKop | last post by:
AnyClass Blah() { AnyClass poo; return poo; } As we all know, in the above, the compiler is entitled to:
25
by: Victor Bazarov | last post by:
In the project I'm maintaining I've seen two distinct techniques used for returning an object from a function. One is AType function(AType const& arg) { AType retval(arg); // or default...
13
by: Matthias Kaeppler | last post by:
Hi, I was wondering why library implementors often make getter functions return strings by value (copies). For example, in boost::filesystem the leaf() function returns an std::string by value....
23
by: pauldepstein | last post by:
Below is posted from a link for Stanford students in computer science. QUOTE BEGINS HERE Because of the risk of misuse, some experts recommend never returning a reference from a function or...
8
by: darren | last post by:
Hi everybody, have a quick look at this code: ===== ===== int main(void) { string msg; makeString(msg); cout << "back in main, result = " << msg << endl;
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.