CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 6 of 6

Thread: references&

  1. #1
    Join Date
    Mar 2000
    Location
    Oxford, UK.
    Posts
    352

    references&

    What's happening here?



    class A {

    };

    A go(void) {
    A a;
    return a;
    }

    int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
    {
    A& aa = go();
    ////
    //// --
    return 0;
    }








    In case it's not obvious, I am wondering whether aa is valid since it is a reference to an object which is destroyed or something.

    \begin{signature}
    digital watches and mobile phones.
    \end{signature}

  2. #2
    Join Date
    Oct 2000
    Location
    London, England
    Posts
    4,773

    Re: references&

    go() returns an object, not a copy. If you peak at A's destructor you will find it is called twice - that is because two of A's constructors are called, the default constructor and the copy constructor.

    It is for this reason that classes like string will often use shared reference counting on the actual string data they return. Otherwise every time a function returned a string it would have to copy the data (inefficient).


    The best things come to those who rate

  3. #3
    Join Date
    Mar 2000
    Location
    Oxford, UK.
    Posts
    352

    Re: references&

    ok, go() returns an object. What is the lifetime of this object? It seems that this depends on whether there are references to it. Try looking at this in a debugger:


    class A {
    public:
    ~A(void) {
    static int i(0);
    ++i;
    };

    };

    A go(void) {
    A a;
    return a;
    }

    int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
    {
    int j;
    #ifdef V1
    A& aa = go();
    #else
    go();
    #endif


    j = 0;

    return 0;
    }





    I thought that reference counting was Java, not C++. From this it seems that C++ does some implicit reference counting,
    and will not destroy an object if there is a reference to it somewhere.

    \begin{signature}
    digital watches and mobile phones.
    \end{signature}

  4. #4
    Join Date
    Apr 1999
    Location
    Altrincham, England
    Posts
    4,470

    Re: references&

    According to the C++ standard:

    a reference initialised with a temporary value makes that temporary value live for the lifetime of the reference itself. (That's the information I've seen, although I've only ever seen a const reference used.)

    So, for

    /* const? */ A& aa = go();



    the temporary has the lifetime of aa, but for

    go();



    the temporary lives until the semicolon. I suppose you could look on this as reference counting, but it's a very limited form.

    He who breaks a thing to find out what it is, has left the path of wisdom - Gandalf
    Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.
    --
    Sutter and Alexandrescu, C++ Coding Standards

    Programs must be written for people to read, and only incidentally for machines to execute.

    --
    Harold Abelson and Gerald Jay Sussman

    The cheapest, fastest and most reliable components of a computer system are those that aren't there.
    -- Gordon Bell


  5. #5
    Join Date
    Jun 2000
    Posts
    351

    Re: references&

    It's a compiler optimization. You don't use the return value, so it gets rid of the object.

    Assigning the reference to it, means you do use the return value, so it does have the life of the reference.

    Contrary to belief... Win32 API programming is easier and cleaner the MFC...

  6. #6
    Join Date
    Apr 1999
    Location
    Altrincham, England
    Posts
    4,470

    Re: references&

    It's a bit more than just an optimisation: I think the standard says that the temporary lasts to the end of the statement that created it. I have a class that returns an object and I rely on it lasting to the end of the statement:

    class C
    {
    struct Proxy_
    {
    Proxy_() {}
    ~Proxy_()
    {
    TRACE("%s", str.str().c_str());
    }
    std:stringstream& str;
    };
    public:
    Proxy_ f()
    {
    return Proxy_();
    }
    // other stuff
    };

    int main()
    {
    C c;

    c.f().str << "messages" << data << etc << endl;
    }



    What this does is to allow me to build up a string using iostream style and then print it to the debug output window. It relies on the temporary Proxy_ object lasting to the end of the statement, at which point the destructor kicks in to actually print the string to the debug window. I suppose you could argue that I'm using the object, so the optimiser won't throw it away, but this behaviour is, I believe, enshrined in the standard.

    He who breaks a thing to find out what it is, has left the path of wisdom - Gandalf
    Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.
    --
    Sutter and Alexandrescu, C++ Coding Standards

    Programs must be written for people to read, and only incidentally for machines to execute.

    --
    Harold Abelson and Gerald Jay Sussman

    The cheapest, fastest and most reliable components of a computer system are those that aren't there.
    -- Gordon Bell


Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured