Unexpected behaviour

Discussion in 'C++' started by Ioannis Vranos, Sep 23, 2004.

  1. For the code


    #include <iostream>

    class Blah
    {
    int i;

    public:

    Blah(const Blah &obj)
    {
    std::cout<<"Copy Constructor called!\n";
    i=obj.i;
    }

    Blah()
    {
    std::cout<<"Default Constructor called!\n"; i=0;
    }
    };


    int main()
    {
    Blah poo1(Blah());

    Blah poo2=Blah();
    }


    I only get

    C:\c>temp
    Default Constructor called!

    C:\c>


    which is produced for the second object while nothing is produced for
    the first.


    Why no message is produced for the first, and why only a default
    constructor message is produced for the second?



    I expected:

    C:\c>temp
    Default Constructor called!
    Copy Constructor called!
    Default Constructor called!
    Copy Constructor called!

    C:\c>



    --
    Ioannis Vranos

    http://www23.brinkster.com/noicys
     
    Ioannis Vranos, Sep 23, 2004
    #1
    1. Advertising

  2. "Ioannis Vranos" <> wrote in message
    news:ciuoco$1q6s$...
    > For the code
    >
    >
    > #include <iostream>
    >
    > class Blah
    > {
    > int i;
    >
    > public:
    >
    > Blah(const Blah &obj)
    > {
    > std::cout<<"Copy Constructor called!\n";
    > i=obj.i;
    > }
    >
    > Blah()
    > {
    > std::cout<<"Default Constructor called!\n"; i=0;
    > }
    > };
    >
    >
    > int main()
    > {
    > Blah poo1(Blah());
    >
    > Blah poo2=Blah();
    > }
    >
    >
    > I only get
    >
    > C:\c>temp
    > Default Constructor called!
    >
    > C:\c>
    >
    >
    > which is produced for the second object while nothing is produced for
    > the first.
    >
    >
    > Why no message is produced for the first, and why only a default
    > constructor message is produced for the second?
    >


    Because this

    Blah poo1(Blah());

    is a function prototype. You can check this by adding the function call at
    the end of main.

    poo1(0);

    Have you been listening to JKop again?

    john
     
    John Harrison, Sep 23, 2004
    #2
    1. Advertising

  3. Ioannis Vranos wrote:
    > For the code
    >
    >
    > #include <iostream>
    >
    > class Blah
    > {
    > int i;
    >
    > public:
    >
    > Blah(const Blah &obj)
    > {
    > std::cout<<"Copy Constructor called!\n";
    > i=obj.i;
    > }
    >
    > Blah()
    > {
    > std::cout<<"Default Constructor called!\n"; i=0;
    > }
    > };
    >
    >
    > int main()
    > {
    > Blah poo1(Blah());
    >
    > Blah poo2=Blah();
    > }
    >
    >
    > I only get
    >
    > C:\c>temp
    > Default Constructor called!
    >
    > C:\c>
    >
    >
    > which is produced for the second object while nothing is produced for
    > the first.


    The statement

    Blah poo1(Blah());

    is a _declaration_ of a function 'poo1'. Read the FAQ.

    >
    >
    > Why no message is produced for the first, and why only a default
    > constructor message is produced for the second?


    Because 'poo1' is not an object.

    >
    >
    >
    > I expected:
    >
    > C:\c>temp
    > Default Constructor called!
    > Copy Constructor called!
    > Default Constructor called!
    > Copy Constructor called!


    Too bad. Study the declaration syntax.

    >
    > C:\c>
    >
    >
    >


    V
     
    Victor Bazarov, Sep 23, 2004
    #3
  4. Ioannis Vranos

    JKop Guest

    > Because this
    >
    > Blah poo1(Blah());
    >
    > is a function prototype. You can check this by adding the

    function call
    > at the end of main.
    >
    > poo1(0);
    >
    > Have you been listening to JKop again?
    >
    > john



    Now that's embarassing...


    -JKop
     
    JKop, Sep 23, 2004
    #4
  5. > >
    > > Have you been listening to JKop again?
    > >
    > > john

    >
    >
    > Now that's embarassing...
    >
    >
    > -JKop


    There was something about Ioannis' code style that gave the game away.

    john
     
    John Harrison, Sep 23, 2004
    #5
  6. John Harrison wrote:

    > Have you been listening to JKop again?


    Ehehehe, we have an expression here in Greece. When you are talking with
    someone telling wrong things, confusion comes out and you say "I will
    forget even what I know".

    That is what happened here, I got confused.


    That said, his intention was good. :)


    BTW in the expression Blah poo=Blah() why not the copy constructor nor
    the default constructor are called?



    --
    Ioannis Vranos

    http://www23.brinkster.com/noicys
     
    Ioannis Vranos, Sep 23, 2004
    #6
  7. Ioannis Vranos, Sep 23, 2004
    #7
  8. Ioannis Vranos wrote:
    > Fixed:
    >
    >
    > BTW in the expression Blah poo=Blah() why only the default constructor
    > is called?


    Because it is allowed to be optimized to do so.

    V
     
    Victor Bazarov, Sep 23, 2004
    #8
  9. Victor Bazarov wrote:

    > Because it is allowed to be optimized to do so.




    However consider this:


    #include <iostream>

    struct Blah
    {
    public:

    int i;

    Blah(const Blah &obj)
    {
    std::cout<<"Copy Constructor called!\n";

    i=10*obj.i;
    }

    Blah()
    {
    std::cout<<"Default Constructor called!\n";

    i=1;
    }

    Blah &operator=(const Blah &obj)
    {
    std::cout<<"Assignment used!\n";

    i=5*obj.i;

    return *this;
    }

    };


    int main()
    {
    Blah poo=Blah();

    std::cout<<poo.i<<std::endl;
    }



    C:\c>temp
    Default Constructor called!
    1

    C:\c>



    Any explanation?



    --
    Ioannis Vranos

    http://www23.brinkster.com/noicys
     
    Ioannis Vranos, Sep 23, 2004
    #9
  10. So in summary we have got:


    T x = T():

    For POD types it is equivalent to initialisation to 0 for built in types
    and all members to 0 for structs.

    [Addition of 2003]: For non-POD types without a default constructor
    definition, also all members to 0.


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


    For non-POD types with a default constructor definition, it is
    equivalent to T x; - no temporary is created and copy constructor is not
    called.



    --
    Ioannis Vranos

    http://www23.brinkster.com/noicys
     
    Ioannis Vranos, Sep 23, 2004
    #10
  11. Ioannis Vranos wrote:
    > So in summary we have got:
    >
    >
    > T x = T():
    >
    > For POD types it is equivalent to initialisation to 0 for built in types
    > and all members to 0 for structs.
    >
    > [Addition of 2003]: For non-POD types without a default constructor
    > definition, also all


    POD

    > members to 0.
    >
    >
    > -----------------------------------------------------------------------
    >
    >
    > For non-POD types with a default constructor definition, it is
    > equivalent to T x; - no temporary is created and copy constructor is not
    > called.




    --
    Ioannis Vranos

    http://www23.brinkster.com/noicys
     
    Ioannis Vranos, Sep 23, 2004
    #11
  12. Ioannis Vranos

    JKop Guest

    > Blah &operator=(const Blah &obj)
    > {
    > std::cout<<"Assignment used!\n";
    >
    > i=5*obj.i;
    >
    > return *this;
    > }



    Irrelevant. The assignment operator isn't called.

    -JKop
     
    JKop, Sep 23, 2004
    #12
  13. Ioannis Vranos

    Rolf Magnus Guest

    Ioannis Vranos wrote:

    > Victor Bazarov wrote:
    >
    >> Because it is allowed to be optimized to do so.

    >
    >
    >
    > However consider this:
    >
    >
    > #include <iostream>
    >
    > struct Blah
    > {
    > public:
    >
    > int i;
    >
    > Blah(const Blah &obj)
    > {
    > std::cout<<"Copy Constructor called!\n";
    >
    > i=10*obj.i;
    > }
    >
    > Blah()
    > {
    > std::cout<<"Default Constructor called!\n";
    >
    > i=1;
    > }
    >
    > Blah &operator=(const Blah &obj)
    > {
    > std::cout<<"Assignment used!\n";
    >
    > i=5*obj.i;
    >
    > return *this;
    > }
    >
    > };
    >
    >
    > int main()
    > {
    > Blah poo=Blah();
    >
    > std::cout<<poo.i<<std::endl;
    > }
    >
    >
    >
    > C:\c>temp
    > Default Constructor called!
    > 1
    >
    > C:\c>
    >
    >
    >
    > Any explanation?


    Same as before. This is allwed as an optimization.
     
    Rolf Magnus, Sep 23, 2004
    #13
  14. More "legally" accurate:


    So in summary we have got:


    T x = T():

    For POD types it is equivalent to initialisation to 0 for built in types
    and all members to 0 for structs.


    [Addition of 2003]: For non-POD types without a default constructor
    definition, also all POD members to 0.


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

    For non-POD types with a default constructor definition, it may be
    considered equivalent to T x; - we may have not a temporary created and
    copy constructor called.



    --
    Ioannis Vranos

    http://www23.brinkster.com/noicys
     
    Ioannis Vranos, Sep 23, 2004
    #14
  15. Ioannis Vranos <> wrote in message news:<ciuoco$1q6s$>...
    >
    > int main()
    > {
    > Blah poo1(Blah());

    This is not a definition of object `poo1'. This is a declaration of
    function poo1 that takes returns Blah and takes argument of type "Blah
    (*)()" - a pointer to function that takes no arguments and returns
    object of type Blah.

    > Blah poo2=Blah();
    > }


    -- Mikhail Kupchik
     
    Mikhail N. Kupchik, Sep 23, 2004
    #15
  16. Ioannis Vranos

    Ron Natalie Guest

    "Ioannis Vranos" <> wrote in message news:civ4j9$2hfj$...
    > So in summary we have got:
    >
    >
    > T x = T():
    >
    > For POD types it is equivalent to initialisation to 0 for built in types
    > and all members to 0 for structs.


    Not ture. In 1999-speak it's default initialization for all types. If T is POD
    types this means zero initialization. If T is not POD, then what ever default
    initailization means for that type.
    >
    > [Addition of 2003]: For non-POD types without a default constructor
    > definition, also all members to 0.


    Addition of 2003, change the working to "value initialization" which is still
    zero initialized for POD's, but for classes with no user defined constructor,
    it means value-initialize each member separately.
     
    Ron Natalie, Sep 23, 2004
    #16
  17. Ron Natalie wrote:
    > "Ioannis Vranos" <> wrote in message news:civ4j9$2hfj$...
    >
    >>So in summary we have got:
    >>
    >>
    >>T x = T():
    >>
    >>For POD types it is equivalent to initialisation to 0 for built in types
    >>and all members to 0 for structs.

    >
    >
    > Not ture. In 1999-speak



    I assume you mean 1998.



    > it's default initialization for all types. If T is POD
    > types this means zero initialization. If T is not POD, then what ever default
    > initailization means for that type.
    >
    >>[Addition of 2003]: For non-POD types without a default constructor
    >>definition, also all members to 0.

    >
    >
    > Addition of 2003, change the working to "value initialization" which is still
    > zero initialized for POD's, but for classes with no user defined constructor,
    > it means value-initialize each member separately.



    OK. As far as I can understand what I said do not contradict with yours,
    right?



    --
    Ioannis Vranos

    http://www23.brinkster.com/noicys
     
    Ioannis Vranos, Sep 23, 2004
    #17
  18. Ioannis Vranos

    Old Wolf Guest

    Ioannis Vranos <> wrote:
    >
    > #include <iostream>
    >
    > class Blah
    > {
    > public:
    > Blah(const Blah &obj) {
    > std::cout<<"Copy Constructor called!\n";
    > }
    > Blah() {
    > std::cout<<"Default Constructor called!\n";
    > }
    > };
    >
    > int main()
    > {
    > Blah poo1(Blah());
    > Blah poo2=Blah();
    > }


    What's with everybody calling their objects 'poo'.

    > I only get
    >
    > Default Constructor called!
    >
    > I expected:
    >
    > Default Constructor called!
    > Copy Constructor called!
    > Default Constructor called!
    > Copy Constructor called!


    Case 1 declares a function 'poo1' returning Blah and taking
    as parameter, a pointer to function taking no parameters and
    returning Blah. So no output is generated.

    In case 2, the compiler optimises out the copy construction.
    This is permitted in some circumstances (eg. this one, and
    in RVO). So you only get the message for the default construction.
     
    Old Wolf, Sep 23, 2004
    #18
  19. Ioannis Vranos

    Zian Smith Guest

    Ioannis Vranos <> wrote in message news:<ciuoco$1q6s$>...
    > For the code
    >


    <snip>

    >
    >
    > int main()
    > {
    > Blah poo1(Blah());


    This is subtle. you are not actually creating a new object called poo1
    here. You are instead declaring a function called poo1 that takes a
    single parameter, and returns an object of type Blah. The single
    parameter that poo1 takes is a pointer to a some function that takes a
    void parameter and returns an object of type Blah.


    > Blah poo2=Blah();


    I'm not sure about this one. You are creating a new object called
    poo2, and creating a temporary object via Blah(). A constructor has to
    be called for poo2 and I would have expected the copy constructor to
    be called. However the default constructor is indeed being called.
    My *GUESS* is that since Blah() generates a temporary object anyways,
    instead of calling the default constructor for the temporary object
    and then the copy constructor for the poo2 object, optimization is
    done, and a single default constructor call for poo2 is made instead.

    However, consider the following: If you overload the + operator for
    the Blah class (so if you "add" two blah objects you get another Blah
    object), the following will call the copy constructor even though the
    + operator generates a temporary object:

    Blah x,y;
    Blah z = x + y; //calls copy constructor for z
    Blah z = Blah() + Blah() //will also call the copy constructor



    -Z.Smith
     
    Zian Smith, Sep 24, 2004
    #19
  20. Ioannis Vranos

    Rolf Magnus Guest

    Zian Smith wrote:

    > Ioannis Vranos <> wrote in message
    > news:<ciuoco$1q6s$>...
    >> For the code
    >>

    >
    > <snip>
    >
    >>
    >>
    >> int main()
    >> {
    >> Blah poo1(Blah());

    >
    > This is subtle. you are not actually creating a new object called poo1
    > here. You are instead declaring a function called poo1 that takes a
    > single parameter, and returns an object of type Blah. The single
    > parameter that poo1 takes is a pointer to a some function that takes a
    > void parameter and returns an object of type Blah.


    This rule looks really stupid to me, and I see many newbies being confused
    by this. Why didn't they just leave it like C and require the keyword void
    to denote an empty parameter list? Then:

    Blah poo1(Blah());

    would just be a default initialization, like one would expect on the first
    sight. If you want instead the function declaration, you would need to
    write:

    Blah poo1(Blah(void));

    Why wasn't it done that way in C++? All those subtle "this isn't an object
    definition - it's a function declaration" problems wouldn't ever have
    existed.

    >> Blah poo2=Blah();

    >
    > I'm not sure about this one. You are creating a new object called
    > poo2, and creating a temporary object via Blah(). A constructor has to
    > be called for poo2 and I would have expected the copy constructor to
    > be called. However the default constructor is indeed being called.
    > My *GUESS* is that since Blah() generates a temporary object anyways,
    > instead of calling the default constructor for the temporary object
    > and then the copy constructor for the poo2 object, optimization is
    > done, and a single default constructor call for poo2 is made instead.


    Yes. That's how it works.

    > However, consider the following: If you overload the + operator for
    > the Blah class (so if you "add" two blah objects you get another Blah
    > object), the following will call the copy constructor even though the
    > + operator generates a temporary object:
    >
    > Blah x,y;
    > Blah z = x + y; //calls copy constructor for z
    > Blah z = Blah() + Blah() //will also call the copy constructor


    That depends. Still some compilers won't call the copy constructor. The
    operator+ can directly construct its return value into z, using what is
    usually referred to as return value optimization. Basically, the calling
    function (where z is defined) just reserves the space and gives the address
    of it as a hidden parameter to the function (or operator in this case),
    which then can directly construct its return value into that address, so
    that no copy is needed.
     
    Rolf Magnus, Sep 24, 2004
    #20
    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. Mark
    Replies:
    4
    Views:
    2,972
    scoude
    Jan 12, 2011
  2. Steven Van den Berghe

    unexpected map behaviour

    Steven Van den Berghe, Aug 28, 2003, in forum: C++
    Replies:
    2
    Views:
    432
    Christian Jan├čen
    Aug 28, 2003
  3. Old Wolf
    Replies:
    1
    Views:
    404
    Victor Bazarov
    Feb 4, 2004
  4. Richard Philips

    Unexpected python behaviour

    Richard Philips, Nov 28, 2003, in forum: Python
    Replies:
    2
    Views:
    326
    Jay O'Connor
    Nov 28, 2003
  5. Simon Wittber

    Unexpected mod-python behaviour.

    Simon Wittber, Feb 4, 2004, in forum: Python
    Replies:
    1
    Views:
    271
    Bengt Richter
    Feb 6, 2004
Loading...

Share This Page