Почему конструктор копирования не вызывается в этой примерной программе?
Когда функция input()
возвращает объект, делается копия объекта, но я не вижу, чтобы конструктор копирования вызывался в соответствии с выходом в консоли.
Вывод:
Enter a string: ssssssssss
ssssssssss
Freeing s
Код:
#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;
}
Конструктор копирования не вызывается, поскольку ваш компилятор выполнил оптимизацию.
Оптимизация называется RVO (или NRVO) и позволяет компилятору при определенных обстоятельствах создавать возвращаемые значения непосредственно на месте вызова.
Большинство компиляторов позволяют вам включать оптимизацию с опцией. Clang и gcc позволяют вам использовать elision, используя:
-fno-elide-constructors
Также ваш код имеет неопределенное поведение, поскольку конструктор копирования не инициализирует s
ничем. Вызов Sample::show
или деструктор объекта, созданного копией, приведет к тому, что UB будет недоступен для доступа или удаления неинициализированных данных.
Кроме того, Sample
класса демонстрирует UB, поскольку он не следует Правилу три (что такое правило три?). Использование неявно объявленного оператора присваивания копии будет выполнять мелкую копию s
которая может привести к тому, что данные, указывающие на то, что они будут удалены несколько раз при уничтожении, что является UB.