0

Why is the copy constructor not called in this sample program?

When the function input() returns an object, a copy of the object is made, but I cannot see that the copy constructor is called according to the output in the console.

Output:

 Enter a string: ssssssssss
 ssssssssss
 Freeing s

Code:

#include <iostream>
using namespace std;

class Sample {
    char *s;
public:
    Sample() { s = 0; }
    Sample(const Sample &sample) { cout << "copyconstructor\n"; }
    ~Sample() { if(s) delete[] s; cout << "Freeing s\n"; }

    void show() { cout << s << "\n"; }

    void set(char *str) {
        s = new char[strlen(str) + 1];
        strcpy(s, str);
    }
};

Sample input() {
    char instr[80];
    Sample str;
    cout << "Enter a string: ";
    cin >> instr;
    str.set(instr);
    return str;
}

int main() {
    Sample ob = input();
    ob.show();
    return 0;
}
Felix Glas
  • 15,065
  • 7
  • 53
  • 82
  • http://en.wikipedia.org/wiki/Copy_elision –  Jun 09 '14 at 10:36
  • 3
    It does not have to be called if [copy ellision](http://en.wikipedia.org/wiki/Copy_elision) and [Return Value Optimization](http://en.wikipedia.org/wiki/Return_value_optimization) are performed. These are allowed optimizations that change observable bahaviour of a program. How do you compile it? You could try with least optimizations possible, but I think the compiler is still free to act upon such an obvious case. Actually the example in the RVO article is exactly your "problem". – luk32 Jun 09 '14 at 10:37
  • I also think it's a combined dupe of those: http://stackoverflow.com/questions/3084753/copy-constructor-is-not-called, http://stackoverflow.com/questions/12686099/copy-constructor-not-calling. 1st is about RVO, 2nd about copy ellision. – luk32 Jun 09 '14 at 10:46

1 Answers1

2

The copy constructor is not called as your compiler has performed an optimization.

The optimization is called RVO (or NRVO) and allows the compiler to construct return values directly in place at the callsite under some circumstances.

Most compilers allow you to turn of optimizations with an option. Clang and gcc allows you to turn of elision using:

-fno-elide-constructors

Also your code has undefined behaviour as the copy constructor does not initialize s to anything. Calling Sample::show or the destructor on a copy constructed object will result in UB as accessing or deleteing uninitialized data is undefined.

Furthermore, the class Sample exhibits UB as it does not follow The Rule of Three (What is The Rule of Three?). Using the implicitly declared copy assignment operator will perform a shallow copy of s which may result in the data pointed to being deleted multiple times on destruction, which is UB.

Community
  • 1
  • 1
Felix Glas
  • 15,065
  • 7
  • 53
  • 82