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

Конструкторы

Функция-член класса с тем же именем, что и у класса, называется конструктором. Она используется для построения этого класса. Конструктор не должен возвращать никакого значения, даже.

class Complex { private: double r, m; public: Complex(double r, double m): r(r), m(m) {} ... };

Если класс имеет конструктор, все объекты этого класса будут проинициализированы. Если конструктору требуются параметры, они должны быть предоставлены.

Когда для класса объявлен конструктор, нельзя пользоваться списком инициализации в качестве инициализатора.

Complex c1(5, -2); Complex c2 = {5, -2}; // Правильно // Ошибка – класс Complex имеет конструктор

Конструктор умолчания

Конструктор умолчания класса Х – это конструктор класса Х, вызываемый без параметров. Конструктор умолчания обычно имеет вид Х :: Х(), однако и конструктор, который может вызываться без параметров, потому что имеет параметры с умолчанием, например, Х :: Х(int = 0), также считается конструктором умолчания. При отсутствии других объявленных конструкторов, конструктор умолчания генерируется компилятором.

class Complex { private: double r, m; public: Complex(double nr = 0, double nm = 0): r(nr), m(nm) {} ... };  
Complex y1(-6, 3); // Вызов конструктора с параметрами
Complex y2; // Конструктор вызывается как конструктор умолчания

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

Конструктор копирования для класса Х – это конструктор, который может быть вызван для копирования объекта класса Х, т.е. такой конструктор, который может быть вызван с одним параметром – ссылкой на объект класса Х. Например, X :: X(const X&) и X :: X(X&, int = 0) являются конструкторами копирования.

При отсутствии объявленных конструкторов копирования компилятор генерирует публичный конструктор копирования. Генерируемый конструктор копирования выполняет побитовое копирование объекта. Этот метод годится лишь при отсутствии в объекте которые хранят адреса динамически распределенной памяти. Сгенерированный конструктор скопирует адрес, а не содержимое памяти, таким образом, два разных объекта будут ссылаться на один и тот участок памяти и меняться синхронно, что не является ожидаемым поведением. В таком случае программист обязательно должен сам написать конструктор копирования, который будет, в частности, копировать содержимое динамически распределённой памяти.

Однако в тех случаях, когда копирующий конструктор по умолчанию имеет правильный смысл, лучше полагаться на это умолчание. Это короче, а читающие код должны понимать умолчания. Кроме того, компилятор знает об этом умолчании и о возможностях его оптимизации. А написание почленного копирования классов с большим количеством членов данных вручную – занятие утомительное, и при этом можно наделать массу ошибок.

Конструктор копирования – и определяемый пользователем, и генерируемый компилятором – используется:

  • при инициализации переменных;
  • при передаче аргументов;
  • при возврате значения из функции;
  • при обработке исключений.

Семантика этих операций по определению совпадает с семантикой инициализации.

Complex x = 2; Complex y = Complex(2, 0); // Создает Complex (2), затем копирует его в x // Создает Complex (2, 0), затем копирует его в у

От вызовов конструктора копирования легко избавиться. С тем же успехом можно записать следующее.

Complex x(2); Complex y(2, 0); // Проинициализировать x значением 2 // Проинициализировать у значением (2, 0)

Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: