Конструктор копирования не называется

0

Почему конструктор копирования не вызывается в этой примерной программе?

Когда функция 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;
}
Показать ещё 1 комментарий
Теги:
copy-constructor
compiler-optimization

1 ответ

2
Лучший ответ

Конструктор копирования не вызывается, поскольку ваш компилятор выполнил оптимизацию.

Оптимизация называется RVO (или NRVO) и позволяет компилятору при определенных обстоятельствах создавать возвращаемые значения непосредственно на месте вызова.

Большинство компиляторов позволяют вам включать оптимизацию с опцией. Clang и gcc позволяют вам использовать elision, используя:

-fno-elide-constructors

Также ваш код имеет неопределенное поведение, поскольку конструктор копирования не инициализирует s ничем. Вызов Sample::show или деструктор объекта, созданного копией, приведет к тому, что UB будет недоступен для доступа или удаления неинициализированных данных.

Кроме того, Sample класса демонстрирует UB, поскольку он не следует Правилу три (что такое правило три?). Использование неявно объявленного оператора присваивания копии будет выполнять мелкую копию s которая может привести к тому, что данные, указывающие на то, что они будут удалены несколько раз при уничтожении, что является UB.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню