a basic question about Object, Object&

Discussion in 'C++' started by gg9h0st, Oct 24, 2006.

  1. gg9h0st

    gg9h0st Guest

    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. :)
    gg9h0st, Oct 24, 2006
    #1
    1. Advertising

  2. gg9h0st

    Jim Langston Guest

    "gg9h0st" <> wrote in message
    news:...
    >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?
    Jim Langston, Oct 24, 2006
    #2
    1. Advertising

  3. gg9h0st

    Gavin Deane Guest

    gg9h0st wrote:
    > i worte a simple code below.


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

    > ------------------------------------------------------------------------------------
    >
    > #include "stdafx.h"


    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
    Gavin Deane, Oct 24, 2006
    #3
  4. gg9h0st

    gg9h0st Guest

    helps alot. greate explanation

    thanks both of you. :)
    gg9h0st, Oct 24, 2006
    #4
  5. gg9h0st

    Salt_Peter Guest

    gg9h0st wrote:
    > i worte a simple code below.
    >
    > ------------------------------------------------------------------------------------
    >
    > #include "stdafx.h"


    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.
    Salt_Peter, Oct 24, 2006
    #5
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Engineer
    Replies:
    6
    Views:
    611
    Jeremy Bowers
    May 1, 2005
  2. Replies:
    0
    Views:
    426
  3. Replies:
    2
    Views:
    267
  4. ibm
    Replies:
    1
    Views:
    269
    Victor Bazarov
    Jun 27, 2005
  5. Ark Khasin

    A basic question question about volatile use

    Ark Khasin, Jul 31, 2008, in forum: C Programming
    Replies:
    12
    Views:
    359
    Ark Khasin
    Jul 31, 2008
Loading...

Share This Page