Copy constructor doesn't get called when initialized by functionreturning object of same class

Discussion in 'C++' started by abhash, Jun 12, 2008.

  1. abhash

    abhash Guest

    I am bit puzzled at the following piece of code I tried:

    ----------------------------------------------------------------------------------
    #include <iostream>
    using namespace std;

    class Test {
    public:
    Test() { cout<<"Cons\n";}
    Test(Test& a) { cout<<"Copy cons\n";}

    };

    Test fun()
    {
    return Test();

    }

    int main()
    {
    cout<<"First way of initialization\n";
    Test t1;
    Test t2 = t1;

    cout<<"\nSecond way of initialization\n";
    Test t3 = fun();
    return 0;

    }

    OUTPUT (when compiled on CC compiler) :

    First way of initialization
    Cons
    Copy cons

    Second way of initialization
    Cons
    ------------------------------------------------------------------------------------

    I am intrigued why second initialization doesn't call copy
    constructor ?
    Aren't we passing the temporary object returned by fun() call to the
    t3 for copying ?
     
    abhash, Jun 12, 2008
    #1
    1. Advertising

  2. abhash

    Ian Collins Guest

    abhash wrote:
    > I am bit puzzled at the following piece of code I tried:


    > <snip>
    >
    > I am intrigued why second initialization doesn't call copy
    > constructor ?
    > Aren't we passing the temporary object returned by fun() call to the
    > t3 for copying ?


    Google for "C++ RVO"

    --
    Ian Collins.
     
    Ian Collins, Jun 12, 2008
    #2
    1. Advertising

  3. abhash

    sumsin Guest

    On Jun 12, 11:05 am, abhash <> wrote:
    > I am bit puzzled at the following piece of code I tried:
    >
    > ----------------------------------------------------------------------------------
    > #include <iostream>
    > using namespace std;
    >
    > class Test {
    > public:
    > Test() { cout<<"Cons\n";}
    > Test(Test& a) { cout<<"Copy cons\n";}


    This is not the right syntax for copy constructor. It should be like:

    Test(const Test& a)

    >
    > };
    >
    > Test fun()
    > {
    > return Test();
    >
    > }
    >
    > int main()
    > {
    > cout<<"First way of initialization\n";
    > Test t1;
    > Test t2 = t1;
    >
    > cout<<"\nSecond way of initialization\n";
    > Test t3 = fun();
    > return 0;
    >
    > }
    >
    > OUTPUT (when compiled on CC compiler) :
    >
    > First way of initialization
    > Cons
    > Copy cons
    >
    > Second way of initialization
    > Cons
    > ------------------------------------------------------------------------------------
    >
    > I am intrigued why second initialization doesn't call copy
    > constructor ?
    > Aren't we passing the temporary object returned by fun() call to the
    > t3 for copying ?
     
    sumsin, Jun 12, 2008
    #3
  4. abhash

    Mirco Wahab Guest

    abhash wrote:
    > I am bit puzzled at the following piece of code I tried:
    > ...
    > #include <iostream>
    > using namespace std;
    > [snipped]
    > First way of initialization
    > Cons
    > Copy cons
    >
    > Second way of initialization
    > Cons
    > ...
    > I am intrigued why second initialization doesn't call copy
    > constructor ?
    > Aren't we passing the temporary object returned by fun() call to the
    > t3 for copying ?


    Why should it? It's not initialized from an
    instantiated object. This question (together
    w/RVO) has been discussed frequently, eg.
    here: http://forums.msdn.microsoft.com/en-US/vclanguage/thread/ac6e87ce-57c8-4916-ac29-fa083cdb94b3/

    BTW, your code wouldn't compile on my gcc (4.3.1)
    I had to modify it like:

    ...
    class Test {
    public:
    Test() { cout<<"Cons\n";}
    Test(const Test& a) { cout<<"Copy cons\n";}
    };
    ...

    so the /const/ was required to get disambiguation?
    I'm not sure if this as required now so in the
    standard, maybe the experts can say a word.

    Regards

    Mirco
     
    Mirco Wahab, Jun 12, 2008
    #4
  5. abhash

    abhash Guest

    On Jun 12, 1:01 pm, Ian Collins <> wrote:
    > abhash wrote:
    > > I am bit puzzled at the following piece of code I tried:
    > > <snip>

    >
    > > I am intrigued why second initialization doesn't call copy
    > > constructor ?
    > > Aren't we passing the temporary object returned by fun() call to the
    > > t3 for copying ?

    >
    > Google for "C++ RVO"
    >
    > --
    > Ian Collins.


    Thanks Ian for pointing to RVO term. Found quite a lucid explanation
    for it here:

    http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=199

    -Amit
     
    abhash, Jun 12, 2008
    #5
  6. Re: Copy constructor doesn't get called when initialized by function returning object of same class

    On Thu, 12 Jun 2008 11:47:10 -0700 (PDT), abhash wrote:
    >Thanks Ian for pointing to RVO term. Found quite a lucid explanation
    >for it here:
    >
    >http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=199


    RVO is a bug in the C++ language. Your copy constructor could contain
    thousands of lines of code (code with side effects) which may be
    blissfully elided by a compiler in the mood.



    --
    Roland Pibinger
    "The best software is simple, elegant, and full of drama" - Grady Booch
     
    Roland Pibinger, Jun 12, 2008
    #6
  7. abhash

    James Kanze Guest

    On Jun 13, 4:11 am, Francis Litterio <> wrote:
    > Roland Pibinger wrote:
    > > On Thu, 12 Jun 2008 11:47:10 -0700 (PDT), abhash wrote:
    > >>Thanks Ian for pointing to RVO term. Found quite a lucid explanation
    > >>for it here:


    > >>http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=199


    > > RVO is a bug in the C++ language. Your copy constructor
    > > could contain thousands of lines of code (code with side
    > > effects) which may be blissfully elided by a compiler in the
    > > mood.


    > But since those "thousands of lines of code" should do nothing
    > but than copy the internal state of the object, the object
    > created by RVO should have state identical to what its state
    > would be if your copy constructor had been invoked.


    But that's not a requirement.

    > Hence, the "O" (Optimization) in RVO.


    The word "bug" isn't correct, because it is an intentional
    compromise. RVO definitly violates the basic C++ object model.
    On the other hand, it can make a significant difference in
    performance with most compilers, AND it shouldn't make a
    significant difference in the behavior of a well designed and
    written program.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orient�e objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place S�mard, 78210 St.-Cyr-l'�cole, France, +33 (0)1 30 23 00 34
     
    James Kanze, Jun 13, 2008
    #7
  8. abhash

    Daniel Pitts Guest

    James Kanze wrote:
    > On Jun 13, 4:11 am, Francis Litterio <> wrote:
    >> Roland Pibinger wrote:
    >>> On Thu, 12 Jun 2008 11:47:10 -0700 (PDT), abhash wrote:
    >>>> Thanks Ian for pointing to RVO term. Found quite a lucid explanation
    >>>> for it here:

    >
    >>>> http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=199

    >
    >>> RVO is a bug in the C++ language. Your copy constructor
    >>> could contain thousands of lines of code (code with side
    >>> effects) which may be blissfully elided by a compiler in the
    >>> mood.

    >
    >> But since those "thousands of lines of code" should do nothing
    >> but than copy the internal state of the object, the object
    >> created by RVO should have state identical to what its state
    >> would be if your copy constructor had been invoked.

    >
    > But that's not a requirement.

    Its not an enforced requirement, but neither is proper synchronization
    in multi-threaded applications. You'll just be sorry if you don't follow
    it, but the compiler will let you do whatever you want. Point gun at
    foot and pull trigger.
    >
    >> Hence, the "O" (Optimization) in RVO.

    >
    > The word "bug" isn't correct, because it is an intentional
    > compromise. RVO definitly violates the basic C++ object model.
    > On the other hand, it can make a significant difference in
    > performance with most compilers, AND it shouldn't make a
    > significant difference in the behavior of a well designed and
    > written program.

    I'm not sure how to respond to this, I haven't been into the depths of
    C++ development long enough to have an opinion on "basic C++ object
    model", and "the behavior of a well designed and written program". I
    think I agree with your second point, but I'm not sure that the basic
    C++ object model is that well defined.

    It does make me wonder if RVO has ever interacted poorly with RAII
    though. Not sure they ever really meet, but if they did, I could see
    anguish and surprise :)

    --
    Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
     
    Daniel Pitts, Jun 14, 2008
    #8
  9. abhash

    James Kanze Guest

    On Jun 14, 8:20 pm, Daniel Pitts
    <> wrote:
    > James Kanze wrote:
    > > On Jun 13, 4:11 am, Francis Litterio <> wrote:
    > >> Roland Pibinger wrote:
    > >>> On Thu, 12 Jun 2008 11:47:10 -0700 (PDT), abhash wrote:
    > >>>> Thanks Ian for pointing to RVO term. Found quite a lucid explanation
    > >>>> for it here:


    > >>>>http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=199


    > >>> RVO is a bug in the C++ language. Your copy constructor
    > >>> could contain thousands of lines of code (code with side
    > >>> effects) which may be blissfully elided by a compiler in the
    > >>> mood.


    > >> But since those "thousands of lines of code" should do nothing
    > >> but than copy the internal state of the object, the object
    > >> created by RVO should have state identical to what its state
    > >> would be if your copy constructor had been invoked.


    > > But that's not a requirement.


    > Its not an enforced requirement, but neither is proper
    > synchronization in multi-threaded applications. You'll just be
    > sorry if you don't follow it, but the compiler will let you do
    > whatever you want. Point gun at foot and pull trigger.


    There's a difference. The lack of proper synchronization in
    multi-threaded applications is undefined behavior. A copy
    constructor which doesn't copy, or does more than just copy, is
    more a style issue; it will confuse the maintenance programmers
    to no end, but hey, that's their problem, not yours:). There's
    also the fact that "proper synchronization" is rigorously
    defined, where as what exactly it means to copy may depend on
    the application. (I have at least one case where a copy
    constructor does modify the logical internal state of the copied
    object.)

    There's one other major difference, too: lack of proper
    synchronization is more or less existing practice (which is one
    reason why so many programs crash all the time), where as a copy
    constructor which doesn't copy is really rare (in my experience,
    and supposing the appropiate definition of "copy").

    > >> Hence, the "O" (Optimization) in RVO.


    > > The word "bug" isn't correct, because it is an intentional
    > > compromise. RVO definitly violates the basic C++ object
    > > model. On the other hand, it can make a significant
    > > difference in performance with most compilers, AND it
    > > shouldn't make a significant difference in the behavior of a
    > > well designed and written program.

    >
    > I'm not sure how to respond to this, I haven't been into the
    > depths of C++ development long enough to have an opinion on
    > "basic C++ object model", and "the behavior of a well designed
    > and written program". I think I agree with your second point,
    > but I'm not sure that the basic C++ object model is that well
    > defined.


    It's very rigorously defined, the copy constructor is a
    constructor, and while it can be provided by the compiler, it
    has no other particular privileges nor, as far as the language
    itself is concerned, responsibilities.

    > It does make me wonder if RVO has ever interacted poorly with
    > RAII though. Not sure they ever really meet, but if they did,
    > I could see anguish and surprise :)


    Most of the time, of course, RAII classes don't support copy.
    But there are exceptions, some of which (e.g. boost::shared_ptr)
    are widely used. The standards committee very definitely
    considered these, and if RVO does cause problems with them, it
    should be considered a bug in the standard. (I think the way
    RVO was originally specified did cause problems in some cases.
    And the specification was modified so that it wouldn't.)

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Jun 14, 2008
    #9
    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. Tom Widmer
    Replies:
    1
    Views:
    522
    Victor Bazarov
    Nov 17, 2004
  2. ali
    Replies:
    4
    Views:
    618
    David Harmon
    Mar 5, 2007
  3. abhash
    Replies:
    4
    Views:
    452
    dizzy
    Jun 12, 2008
  4. cinsk
    Replies:
    35
    Views:
    2,724
    James Kanze
    Oct 11, 2010
  5. Skybuck Flying
    Replies:
    2
    Views:
    2,652
    Alf P. Steinbach /Usenet
    Jun 21, 2011
Loading...

Share This Page