0

I was doing some tests on copy constructors and operator=, but I got some weird results.

Here are my two test files test.h and test.cpp:

test.h

class CopyC {
public:
    CopyC() {
        cout << ">> In Default Constructor" << endl;
    }
    CopyC(const CopyC &other) {
        cout << ">> In Copy Constructor" << endl;
    }
    ~CopyC() {
        cout << ">> In Deconstructor" << endl;
    }

    CopyC& operator=(const CopyC &other) {
        cout << ">> In Operator =" << endl;
        return *this;
    }

    CopyC getCopy() {
        cout << ">> In getCopy" << endl;
        cout << "return CopyC()" << endl;
        return CopyC();
    }
};

test.cpp

#include "test.h"

int main() {
    cout << "CopyC c1" << endl;
    CopyC c1;
    cout << "CopyC c2 = c1.getCopy()" << endl;
    CopyC c2 = c1.getCopy();

    cout << "<< Finish" << endl;
}

I was using gcc 4.6.3 on linux amd64 with the command g++ -o test -g3 test.cpp. The output of ./test is

CopyC c1
>> In Default Constructor
CopyC c2 = c1.getCopy()
>> In getCopy
return CopyC()
>> In Default Constructor
<< Finish
>> In Deconstructor
>> In Deconstructor

It seems that neither the copy constructor nor the operator= are invoked in the getCopy function. Did I missed something or I misunderstood something? Please help. Thanks in advance.

update: Thanks to @Mike Seymour, now I know that this is a problem of copy elision. When I disabled g++ copy elision with g++ -o test test.cpp -fno-elide-constructors, the output looks more resonable:

CopyC c1
>> In Default Constructor
CopyC c2 = c1.getCopy()
>> In getCopy
return CopyC()
>> In Default Constructor
>> In Copy Constructor
>> In Deconstructor
>> In Copy Constructor
>> In Deconstructor
<< Finish
>> In Deconstructor
>> In Deconstructor
mawenbao
  • 259
  • 4
  • 13
  • 2
    Do none of the related questions on the right answer your question? That would surprise me greatly. – chris Feb 27 '14 at 05:12

4 Answers4

0

CopyC() in getCopy() function will call the default constructor

CopyC c2 = c1 will invoke copy constructor

refer to Copy constructor vs. return value optimization

The standard says that the copy constructor need not be used - see section 12.8/15:

15 Whenever a temporary class object is copied using a copy constructor, and this object and the copy have the same cv-unqualified type, an implementation is permitted to treat the original and the copy as two different ways of referring to the same object and not perform a copy at all, even if the class copy constructor or destructor have side effects.

Community
  • 1
  • 1
michaeltang
  • 2,850
  • 15
  • 18
  • That doesn't explain why the copy constructor **isn't** invoked for `CopyC c2 = c1.getCopy();`. Luckily, there are plenty of duplicate questions explaining copy elision. – Mike Seymour Feb 27 '14 at 05:17
0

In getCopy() function, you're calling CopyC() which is default constructor. For copy constructor function that you've written, you should call CopyC(c1) in getCopy() function.

yuvi
  • 1,032
  • 1
  • 12
  • 22
0

It appears that the error might be in the the getCopy() function.

CopyC getCopy() {
    cout << ">> In getCopy" << endl;
    cout << "return CopyC()" << endl;
    return CopyC();
}

getCopy expects an object of class CopyC to be returned but instead the function CopyC() is returned which doesn't return anything itself. A solution would be to create a CopyC object and return that.

CopyC getCopy() {
    cout << ">> In getCopy" << endl;
    cout << "return CopyC()" << endl;
    CopyC copy;
    return copy;
}
Mykle Nero
  • 85
  • 1
  • 6
0

some complier provide an optimization called "Name Return Value" .

CopyC getCopy() {
cout << ">> In getCopy" << endl;
cout << "return CopyC()" << endl;
return CopyC();

}

The code perhaps looks like this in complier :

void getCopy(CopyC &__result){
.....
__result.CopyC::CopyC();   

}

so, neither the copy constructor nor the operator= are invoked in the getCopy function. I hope it helps.

Detergent
  • 1
  • 1