#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
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
> 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.
>
> 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.
>> 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
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
That *isn't* clearer in any way.
> JKop wrote in news:5uiBc.2728$Z14....@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
Anyway, this has been addressed elsewhere in the thread.
END
-JKop
>>
>> 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
> Rob Williscroft posted:
>
>> JKop wrote in news:5uiBc.2728$Z14....@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]
> int Monkey(void)
> {
> int monkey = 72;
>
> return monkey; }
>
Undefined behaviour???????????????????????????????????
-JKop
>
> 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
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
>
> 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.
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.
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
> 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
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