408_____________________Часть III. Современное программирование на C++
Во-первых, имейте в виду, что если вы не определите для нового класса конструктор копий, то C++ создаст его сам (табл. 17.1). Причина заключается в том, что компилятору самому может потребоваться возможность создания копий; значит, эти две функции обязаны быть определены. Во-вторых, вам может потребоваться заблокировать копирование, либо вести подсчет ссылок, или еще что-нибудь. Ерли вы не создадите эти функции, то C++ создаст для них версии по умолчанию.
Создаваемые компилятором версии обеих этих функций не всегда будут вас удовлетворять. Версии компилятора выполняют буквальное, или поразрядное, копирование. В некоторых случаях это неразумно. Не пожалейте времени на изучение ситуаций, которые могут вам встретиться при разработке программ.
Вот лишь некоторые из бесчисленного множества возможных ситуаций, в которых происходит копирование:
Х х; Х у(х); // Прямой вызов конструктора копий. Х х = у; // Выглядит как присваивание, но
// вызывает конструктор копий. Почему?
// См. нижеследующее Замечание Х х, у; х = у; // Вызов операции присваивания Х Foo(); // Возврат по значению, вызывает копирование void Foo ( X) ; // Передача по значению, создает копию
Во всех этих случаях выполняется копирование. В ходе выполняемой компилятором оптимизации могут появиться и другие варианты. Это та область, где знание действительно сила, способная помочь вам избежать утечек памяти.
Замечание
В операторе типа х х = у; не вызывается операция присваивания класса х, хотя выглядит это именно так. Причина состоит в том, что операция присваивания — это функция-член, а значит может быть вызвана только для существующих объектов, в то время как в этом фрагменте происходит создание нового объекта х.
Если объект создается в той же строке, в которой он выступает в качестве левостороннего аргумента, то вызывается конструктор. Строка
Х х = у; // вызов конструктора копий
эквивалентна строке
Х х(у); // вызов конструктора копий
что совсем не то же самое, что
Х х, у;
х = у; // вызов операции присваивания