a basic question about Object, Object&

G

gg9h0st

i worte a simple code below.

------------------------------------------------------------------------------------

#include "stdafx.h"

class Object {
public:
int a;

Object() {
a = 100;
}
};

Object aFunction() {
return Object();
}

Object& bFunction() {
return Object();
}

int _tmain(int argc, _TCHAR* argv[])
{
std::cout << aFunction().a << std::endl;

std::cout << bFunction().a << std::endl;
return 0;
}

----------------------------------------------------------------------------------

as i see the two different return type, Object, Object&, do same thing.

the results are both printing 100.

but i see a warnning message from compiling this code.

what's the difference between Object and Object&?

i see Object& as a return type and an argument.

plz can anyone explain it?

thanks in advance. :)
 
J

Jim Langston

gg9h0st said:
i worte a simple code below.

------------------------------------------------------------------------------------

#include "stdafx.h"

class Object {
public:
int a;

Object() {
a = 100;
}
};

Object aFunction() {
return Object();
}

Object& bFunction() {
return Object();
}

int _tmain(int argc, _TCHAR* argv[])
{
std::cout << aFunction().a << std::endl;

std::cout << bFunction().a << std::endl;
return 0;
}

----------------------------------------------------------------------------------

as i see the two different return type, Object, Object&, do same thing.

the results are both printing 100.

but i see a warnning message from compiling this code.

what's the difference between Object and Object&?

i see Object& as a return type and an argument.

plz can anyone explain it?

thanks in advance. :)

Object& is a reference.
Object is an instance.

For this purpose only, think of Object& as Object*, since a reference is a
pointer on steroids.

Now look at your method:
Object& bFunction() {
return Object();
}

You are returning a refernce (pointer) to a termporary object. The problem
is, this object is going to go away very quickly, since it's only a
temporary object.

For the purpost here it's (probably) okay, since you are not trying to do
anything with it. Consider if you had done this:

Object& MyObject = bFunction();

std::cout << MyObject.a << std::endl;
That last line would probably crash with a memory error (or not, undefined
behavior). The reason is bFunction() created a temporary object and
returned a reference to it, which is stored in MyObject. After that line is
finished, the temporary goes away (if not sooner). Now MyObject is pointing
to memory that no longer (necessarily) contains an instance of Object.

Same as if you had done this:

Object* cFunction()
{
return &(Object());
}

Returning the address of a temporary variable (which is the same thing your
bFunction is doing, it's just wrapped in a refernce).

Understand?
 
G

Gavin Deane

gg9h0st said:
i worte a simple code below.

Are you sure you wrote it and not some automatic code generator that
comes with your compiler?

What's stdafx.h?
class Object {
public:
int a;

Object() {
a = 100;
}
};

Side issues: Your data member should be private and your constructor
should use an intialiser list, not assignment in the constructor body.
Object aFunction() {

That signature says that aFunction returns an object of type "Object"
by value.
return Object();
}

This statement creates an unnamed temporary object of type "Object" and
returns it. The unnamed temporary ceases to exist at the end of this
statement. Because the function returns by value, before the unnamed
temporary is destroyed, a copy is made and that copy is returned to the
function that called aFunction.
Object& bFunction() {

That signature says that bFunction returns a reference to an object of
type "Object". A reference is not the object itself, it is an alias for
the object. So the object referred to needs to exist somewhere.
return Object();

This statement creates an unnamed temporary object of type "Object" and
returns it. The unnamed temporary ceases to exist at the end of this
statement. Because the function returns by reference, the returned
reference is intialised with (and so is an alias for) this unnamed
temporary. But as soon as this statement ends, the unnamed temporary is
destroyed. The reference is returned to the function that called
bFunction, but the object to which that reference refers no longer
exists. Any attept to use that reference invokes undefined behavior.
}

int _tmain(int argc, _TCHAR* argv[])

The _tmain and _TCHAR parts of that code are not standard C++
{
std::cout << aFunction().a << std::endl;

aFunction returns an object. That object is a copy of the unnamed
temporary that was created and destroyed within aFunction. So this code
will output 100.
std::cout << bFunction().a << std::endl;

bFunction returns a reference to an object. That object referred to is
the unnamed temporary that was created and destroyed within bFunction.
Because the referred to object has been destroyed, the behaviour of
your code is undefined. Anything can happen.
return 0;
}

----------------------------------------------------------------------------------

as i see the two different return type, Object, Object&, do same thing.

the results are both printing 100.

That's because you were unlucky. The use of the return value of
bFunction invokes undefined behaviour. Anything can happen and one of
the possbilities is that the code does exaclt what you think it should
do. As far as the C++ language is concerned, the behaviour would be no
more or less correct if it printed 200 instead of 100, or if it printed
"hello world", or if it emailed "hello world" to everyone in your
address book, or if it formatted your hard drive.
but i see a warnning message from compiling this code.

Good. Your compiler may well have a setting that lets you treat
warnings as errors and so prevent successful compiling if a warning is
issued. If you can find this setting, turn it on. The compiler is your
friend. Help it to help you.
what's the difference between Object and Object&?

In your case, the latter invokes undefined behaviour, which is a Bad
Thing.
i see Object& as a return type and an argument.

http://www.parashift.com/c++-faq-lite/references.html

Gavin Deane
 
S

Salt_Peter

gg9h0st said:
i worte a simple code below.

stdafx.h is not needed here, disable precompiled headers in your
project.
class Object {
public:
int a;

Object() {
a = 100;
}
};

use the init list in your ctors, the struct is just a suggestion:

struct Object
{
int a;
Object() : a(100) { }
};
Object aFunction() {
return Object();
}

the above returns an Object by value.
Object& bFunction() {
return Object();
}

the above returns a reference to a local variable (which is about be
get zapped)
int _tmain(int argc, _TCHAR* argv[])

int main()
{
std::cout << aFunction().a << std::endl;

std::cout << bFunction().a << std::endl;
return 0;
}

----------------------------------------------------------------------------------

as i see the two different return type, Object, Object&, do same thing.

the results are both printing 100.

but i see a warnning message from compiling this code.

what's the difference between Object and Object&?

i see Object& as a return type and an argument.

plz can anyone explain it?

When you are faced with an issue like this, equip the compiler to show
you the sequence of events.

Note how construction and destruction of the local copy happens
*before* the copy ctor is invoked in the code below. You'll say "but
its working correctly" and the standard response is: what if object_b
was itself a reference? What guarentees do you have that the remnants
of that zapped local do not get overwritten somewhere down the line?
Can you say - nasty, nasty bug? The compiler sees the remnants of the
local copy as free, available memory space just begging to be reused.

#include <iostream>

struct Object
{
int a;
Object() : a(100) { std::cout << "Object()" << std::endl; }
Object(const Object& copy)
{
a = copy.a;
std::cout << "Object(const Object& copy)" << std::endl;
};
~Object() { std::cout << "~Object()" << std::endl; }
};

const Object& bFunction()
{
return Object();
}

int main()
{
Object object_b = bFunction();
std::cout << object_b.a << std::endl;

return 0;
}

/*
Object()
~Object()
Object(const Object& copy)
100
~Object()
*/

Now change the function so it returns an Object and note what the
compiler does when it optimizes.

Object()
100
~Object()

You can add a parametized ctor to Object if you like, same result.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,780
Messages
2,569,608
Members
45,242
Latest member
KendrickKo

Latest Threads

Top