Thread: Copy constructor question

  1. #1
    Veni Vidi Vice
    Join Date
    Aug 2001
    Posts
    343

    Copy constructor question

    Could someone explain why not the copy-constructor is invoked??
    Code:
    class Test
    {
    public:
    	Test(int tal1, float tal2);
    	~Test();
    	Test(const Test &rhs);
    
    	Test operator+(const Test &arg2);
    
    	int getInttal() const;
    	float getFloattal() const;
    private:
    	int _ital;
    	float _ftal;
    };
    
    Test::Test(int tal, float tal2):
    _ital(tal), _ftal(tal2)
    {
    	cout << "cstr called" << endl;
    }
    
    Test::Test(const Test &rhs):
    _ital(rhs._ital), _ftal(rhs._ftal)
    {
    	cout << "COPY" << endl;
    }
    
    Test::~Test()
    {
    	cout << "decstr" << endl;
    }
    
    
    Test Test::operator+(const Test &arg2)
    {
    	return Test(_ital + arg2._ital, _ftal + arg2._ftal);
    }
    
    
    int Test::getInttal() const
    {
    	return _ital;
    }
    
    float Test::getFloattal() const
    {
    	return _ftal;
    }
    
    
    int main()
    {
    
    Test numb1(10, 25.5f);
    Test numb2(5, 40.5f);
    
    //Copy contructor is not called
    Test sum(numb1 + numb2);
    
    return 0;	
    }
    The overloaded+operator returns a temporary Test object and that object i passed as an argument to the copy-constructor. It seems that neither the constructor or the copy-consrcutor is invoked when the sum object is declared. When I run the program it seems that the constructor is invoked 3 times. And when a change the code to

    Code:
    int main()
    {
    
    Test numb1(10, 25.5f);
    Test numb2(5, 40.5f);
    
    numb1 + numb2;
    
    return 0;	
    }
    it proves that the operator+ is invoked and returns a temporary object (3:rd). Why isnīt the copyconstructor invoked in the statement
    Code:
    Test sum(numb1 + numb2);

  2. #2
    Open to suggestions Brighteyes's Avatar
    Join Date
    Mar 2003
    Posts
    204
    Why isnīt the copyconstructor invoked in the statement
    Because you're not calling the copy constructor anywhere. This line
    Code:
    return Test(_ital + arg2._ital, _ftal + arg2._ftal);
    calls this constructor
    Code:
    Test(int tal1, float tal2);
    since you're passing it individual members and not the complete object. If you changed the operator+ to this
    Code:
    Test Test::operator+(const Test &arg2)
    {
        Test t(_ital + arg2._ital, _ftal + arg2._ftal);
        return t;
    }
    then the copy constructor would be called because a copy has to be made of t since it's a local object. However, by returning an object by way of the constructor as you do, you avoid creating an unnecessary temporary, thus avoiding the copy constructor.
    p.s. What the alphabet would look like without q and r.

  3. #3
    Skunkmeister Stoned_Coder's Avatar
    Join Date
    Aug 2001
    Posts
    2,572
    What you have "discovered" is actually a well known optimization called the return value optimization. It works because the standard allows your compiler to eliminate unnecessary temporaries. But on the other hand rewriting your operator + so that the copy con gets called introduces a named object. a named object can never be eliminated by your compiler.
    Free the weed!! Class B to class C is not good enough!!
    And the FAQ is here :- http://faq.cprogramming.com/cgi-bin/smartfaq.cgi

  4. #4
    Registered User
    Join Date
    Jan 2003
    Posts
    311
    Originally posted by Brighteyes
    If you changed the operator+ to this
    Code:
    Test Test::operator+(const Test &arg2)
    {
        Test t(_ital + arg2._ital, _ftal + arg2._ftal);
        return t;
    }

    then the copy constructor would be called because a copy has to be made of t since it's a local object. However, by returning an object by way of the constructor as you do, you avoid creating an unnecessary temporary, thus avoiding the copy constructor.
    Actually, your operator + is a canidate for named return value optomization. That is, t just pretends to be a local object, it's actually using sum, or whatever was going to be copy constructed from the return value. Add a second local or temporary Test object and all bets are off. Although a really really aggressive compiler might very well try some form of "picked" named return value optomization, though I don't think any of the do so today.

  5. #5
    Veni Vidi Vice
    Join Date
    Aug 2001
    Posts
    343
    k, I think I get it now (will always use this optimization ), but what do you mean when you say

    But on the other hand rewriting your operator + so that the copy con gets called introduces a named object. a named object can never be eliminated by your compiler.
    Like a memory leak?

  6. #6
    Skunkmeister Stoned_Coder's Avatar
    Join Date
    Aug 2001
    Posts
    2,572
    no here there is no named object....
    Code:
    return Test(_ital + arg2._ital, _ftal + arg2._ftal);
    Although this looks like it should make a temporary that temp is not a NAMED object so it can be eliminated by all good compilers.

    Code:
    Test Test::operator+(const Test &arg2)
    {
        Test t(_ital + arg2._ital, _ftal + arg2._ftal);
        return t;
    }
    This on the other hand introduces a named object called t. This because it is named cannot be eliminated by the compiler.
    Why cant we eliminate named objects. Well consider whenever you write multithreaded code you use a lock variable similar to this...
    Code:
    int myfunc()
    {
       Lock lock;
       // this is all inside a critical section
    } // lock is destructed here releasing crit sec.
    Now in this function to a compiler it could easily look like we could eliminate lock because it is not used in this function but your compiler cannot work out on its own that without that lock the code would be unsafe in a multithreaded environment.Because we have named it that means the compiler may not eliminate it. Whether it thinks elimination is a good idea or not it has to do what the c++ standard says and it says named objects cannot be eliminated.
    Free the weed!! Class B to class C is not good enough!!
    And the FAQ is here :- http://faq.cprogramming.com/cgi-bin/smartfaq.cgi

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. copy = concatenate ?
    By Arruba in forum C Programming
    Replies: 3
    Last Post: 11-03-2006, 04:54 PM
  2. calling copy constructor from template
    By Ancient Dragon in forum C++ Programming
    Replies: 3
    Last Post: 09-28-2005, 01:54 PM
  3. dynamic memory alloccation & returning objects
    By haditya in forum C++ Programming
    Replies: 8
    Last Post: 04-21-2005, 11:55 PM
  4. Copy Constructor crashing program
    By bob2509 in forum C++ Programming
    Replies: 5
    Last Post: 11-12-2002, 04:21 PM
  5. Copy Constructor Help
    By Jubba in forum C++ Programming
    Replies: 2
    Last Post: 11-07-2001, 11:15 AM