Thread: Temporary object created by calling constructor

  1. #1
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629

    Temporary object created by calling constructor

    Hi, I was wondering if this idea I have is correct, I couldn't find an answer online

    if i had a simple class
    Code:
          class Dog
         { 
                Dog(x,y);
                public:
    
                void   coolFunction(Dog) ;//Receives object of type Dog as parameter
    
                private: 
                  int x;
                  
                  int y ;
    
              }
    So since the coolFunction(Dog Object) takes an object of type Dog, instead of declaring a
    new object Dog dog1
    and do this
    Code:
              coolFunction(dog1); ...//first method
    I should be able to do this
    Code:
               coolFunction(Dog(4,4)) ; //second method
    I believe that that the second method will create a temporary object in memory by calling the Vector(x,y) constructor,.. and when that copy is passed to the coolFunction(...) the object is then destroyed.


    Can someone tell me if that is wrong or right?
    Or if that is a good practice or idea..i know in C# the same concept is used or it is acceptable.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    You can track constructor and destructor invocations to see what is happening. Note that copy construction can be elided by the compiler as an optimisation.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629
    Quote Originally Posted by laserlight View Post
    You can track constructor and destructor invocations to see what is happening. Note that copy construction can be elided by the compiler as an optimisation.
    Thanks for reply.
    Yes, I know that but when I did this

    coolFunction ( Dog(x,y) )

    I am referring to Dog constructor being called in the parameter coolFunction..

    by doing that Dog(x,y) am I creating a <b>new</b> object although this object is temporary because I am <b>not</b> declaring a variable
    so once the value is passed to the function, this temporary object is destroyed.. because it isn't a variable
    do you understand what I mean?

  4. #4
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    It depends how aggressive the compiler is with optimisation.

    If you and I can see that the two lines are equivalent (apart from the number of temporaries involved) then the compiler is allowed to detect that and elide temporaries.

    Compilers aren't required to do that, but they are allowed to.

    Which means that classes, and code that uses such classes, should not be constructed in a way that relies on any particular behaviour with temporaries - the net effects (other than performance and similar quality attributes) should be the same regardless of how the compiler treats temporaries.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    I understand what you mean, but do you understand what I mean? Basically, my answer to you is yes, you're right. However, due to copy constructor elision, you may find that the temporary is not destroyed once the value is passed to the function. Rather, it is destroyed when control leaves the function, and in fact it is constructed in the same place as the parameter of the function.

    To see this for yourself, you should track constructor and destructor invocation. Print the this pointer and the address of the function's parameter. If you are unable to observe this, try increasing the optimisation level.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #6
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629
    Quote Originally Posted by grumpy View Post
    It depends how aggressive the compiler is with optimisation.

    If you and I can see that the two lines are equivalent (apart from the number of temporaries involved) then the compiler is allowed to detect that and elide temporaries.

    Compilers aren't required to do that, but they are allowed to.

    Which means that classes, and code that uses such classes, should not be constructed in a way that relies on any particular behaviour with temporaries - the net effects (other than performance and similar quality attributes) should be the same regardless of how the compiler treats temporaries.
    sorry I didn't get any of that. In English please?
    so..when I "call" the constructor it <b>does</b> create a temporary object ?

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Eman
    when I "call" the constructor it <b>does</b> create a temporary object ?
    Conceptually, yes.

    Compile and run this program:
    Code:
    #include <iostream>
    
    class Dog
    { 
    public:
        Dog(int x, int y) : x(x), y(y)
        {
            std::cout << "Dog(int, int) of " << this << std::endl;
        }
    
        Dog(const Dog& other) : x(other.x), y(other.y)
        {
            std::cout << "Dog copy ctor of " << this << std::endl;
        }
    
        ~Dog()
        {
            std::cout << "Dog dtor of " << this << std::endl;
        }
    
        void coolFunction(Dog other)
        {
            std::cout << "coolFunction(Dog) of " << this
                << "; parameter: " << &other << std::endl;
        }
    private:
        int x;
        int y;
    };
    
    int main()
    {
        Dog a(1, 2);
        a.coolFunction(Dog(4, 4));
    }
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629
    Quote Originally Posted by laserlight View Post
    Conceptually, yes.

    Compile and run this program:
    Code:
    #include <iostream>
    
    class Dog
    { 
    public:
        Dog(int x, int y) : x(x), y(y)
        {
            std::cout << "Dog(int, int) of " << this << std::endl;
        }
    
        Dog(const Dog& other) : x(other.x), y(other.y)
        {
            std::cout << "Dog copy ctor of " << this << std::endl;
        }
    
        ~Dog()
        {
            std::cout << "Dog dtor of " << this << std::endl;
        }
    
        void coolFunction(Dog other)
        {
            std::cout << "coolFunction(Dog) of " << this
                << "; parameter: " << &other << std::endl;
        }
    private:
        int x;
        int y;
    };
    
    int main()
    {
        Dog a(1, 2);
        a.coolFunction(Dog(4, 4));
    }

    Cool so it does create an object, and it dies when it goes out of scope... ?

  9. #9
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Eman
    Cool so it does create an object, and it dies when it goes out of scope... ?
    The answer to that is definitely a yes, but how you understand the "yes" is another matter. I suggest that you change the main function to this:
    Code:
    int main()
    {
        Dog a(1, 2);
        std::cout << "before" << std::endl;
        a.coolFunction(Dog(4, 4));
        std::cout << "after" << std::endl;
    }
    Then try with this:
    Code:
    int main()
    {
        Dog a(1, 2);
        Dog b(4, 4);
        std::cout << "before" << std::endl;
        a.coolFunction(b);
        std::cout << "after" << std::endl;
    }
    You will probably find considerable difference between the two, but in theory they could actually amount to the same thing (in terms of number of constructor and destructor invocations) if the copy constructor was not elided in the first snippet.

    So, unless you need to copy the argument anyway, you should generally prefer to have your parameters of class type be (const) references.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  10. #10
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629
    Quote Originally Posted by laserlight View Post
    The answer to that is definitely a yes, but how you understand the "yes" is another matter. I suggest that you change the main function to this:
    Code:
    int main()
    {
        Dog a(1, 2);
        std::cout << "before" << std::endl;
        a.coolFunction(Dog(4, 4));
        std::cout << "after" << std::endl;
    }
    Then try with this:
    Code:
    int main()
    {
        Dog a(1, 2);
        Dog b(4, 4);
        std::cout << "before" << std::endl;
        a.coolFunction(b);
        std::cout << "after" << std::endl;
    }
    You will probably find considerable difference between the two, but in theory they could actually amount to the same thing (in terms of number of constructor and destructor invocations) if the copy constructor was not elided in the first snippet.

    So, unless you need to copy the argument anyway, you should generally prefer to have your parameters of class type be (const) references.

    It took me a while to reply because I was trying to understand what was happening lol.
    So the difference in what was happening is that once the copy constructor of one object was called the second program was called
    while the second one wasn't.

    I can only assume that when I did this coolFunction(Dog(4,4)) I am not passing a reference to an "actual" object in memory. i'm not sure how to explain it, but Dog(4,4) isn't concrete...?

    while coolFunction(b) will call the copy constructor because it has a "valid/concrete" address in memory.
    I'm not sure how to explain it

  11. #11
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Eman
    I can only assume that when I did this coolFunction(Dog(4,4)) I am not passing a reference to an "actual" object in memory. i'm not sure how to explain it, but Dog(4,4) isn't concrete...?

    while coolFunction(b) will call the copy constructor because it has a "valid/concrete" address in memory.
    I'm not sure how to explain it
    Take a look at what the C++ standard has to say about this:
    Quote Originally Posted by C++03 Clause 12.8 Paragraph 15 (example omitted)
    When certain criteria are met, an implementation is allowed to omit the copy construction of a class object, even if the copy constructor and/or destructor for the object have side effects. In such cases, the implementation treats the source and target of the omitted copy operation as simply two different ways of referring to the same object, and the destruction of that object occurs at the later of the times when the two objects would have been destroyed without the optimization. This elision of copy operations is permitted in the following circumstances (which may be combined to eliminate multiple copies):
    • in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object with the same cv-unqualified type as the function return type, the copy operation can be omitted by constructing the automatic object directly into the function's return value
    • when a temporary class object that has not been bound to a reference would be copied to a class object with the same cv-unqualified type, the copy operation can be omitted by constructing the temporary object directly into the target of the omitted copy
    So, it is not that Dog(4, 4) is not "concrete", but that the compiler elided the copying of the temporary object by treating it as the same object as the parameter.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  12. #12
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629
    Quote Originally Posted by laserlight View Post
    Take a look at what the C++ standard has to say about this:

    So, it is not that Dog(4, 4) is not "concrete", but that the compiler elided the copying of the temporary object by treating it as the same object as the parameter.
    mmn, thanks very much. I don't really get it because I haven't covered copy constructors yet.since I am learning C++ blindly what I am learning isn't in order. I will save this link and refer to it next when I have covered CC.

    and where can I find this C++ standard?
    Ty

  13. #13
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629

    I promised to get back to this.

    With better understanding of Copy Constructor.
    I want to clarify the difference between doing this

    Code:
       a.coolFunction(Dog(4,4) ) ; 
       //and 
      a.coolFunction(b) ;
    The compiler does not see Dog(4,4) as a already existing object, so therefore did not have any reason to invoke the copy constructor.
    as a result it calls this constructor
    Code:
        Dog(int x, int y) : x(x), y(y)
        {
            std::cout << "Dog(int, int) of " << this << std::endl;
        }
    but for this piece of code a.coolFunction(b)
    the compiler sees the reason to use a copy constructor to copy the already defined object.

    That's an attempt to explain it to myself...

  14. #14
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Eman
    The compiler does not see Dog(4,4) as a already existing object, so therefore did not have any reason to invoke the copy constructor.
    No, whether or not it has a reason to invoke the copy constructor depends on the corresponding parameter of the coolFunction member function. If pass by value is used, then the copy constructor should be invoked, but may be elided.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  15. #15
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629
    OK, yes correct,
    i will refer to your quote, to clear things up:
    So, it is not that Dog(4, 4) is not "concrete", but that the compiler elided the copying of the temporary object by treating it as the same object as the parameter.
    I don't get the last part of it
    <b>treating it as the same object as the parameter.</b>
    Do you mean that it looks at the overloaded constructor signature and therefore as a result may elide the use of the copy constructor depending on that.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. circular doubly linked list help
    By gunnerz in forum C++ Programming
    Replies: 5
    Last Post: 04-28-2007, 08:38 PM
  2. Temporary object debacle
    By verbity in forum C++ Programming
    Replies: 3
    Last Post: 04-24-2007, 11:37 PM
  3. calling constructor crashes program?
    By ichijoji in forum C++ Programming
    Replies: 6
    Last Post: 07-04-2003, 11:17 AM
  4. Calling constructor of the base class of a derived class..
    By CaptainPenguin in forum C++ Programming
    Replies: 5
    Last Post: 02-19-2003, 01:47 PM
  5. Calling an object in a function
    By fry in forum Game Programming
    Replies: 6
    Last Post: 08-10-2002, 11:31 PM