Урок №142. Копирующая инициализация

  Юрий  | 

    | 

  Обновл. 23 Июн 2019  | 

 4684

 ǀ   2 

Рассмотрим следующую строчку кода:

Здесь используется копирующая инициализация для инициализации целочисленной переменной a значением 7. С обычными переменными всё просто. Однако с классами дела обстоят несколько сложнее, поскольку в их инициализации используются конструкторы. В этом уроке мы рассмотрим использование копирующей инициализации с классами.

Использование копирующей инициализации с классами

Рассмотрим следующую программу:

Результат выполнения программы выше:

7/1

Форма копирующей инициализации в примере выше обрабатывается точно так же, как и следующая:

А, как мы уже знаем из предыдущего урока, это может привести к вызову как Drob(int, int), так и конструктора копирования Drob (который может быть проигнорирован). Однако, поскольку гарантии на 100% игнорирование конструктора копирования не предоставляется, то лучше избегать использования копирующей инициализации при работе с классами и вместо неё использовать прямую или uniform инициализацию, так как в случае с использованием конструктора копирования у вас может получиться следующий результат:

7

Вместо следующего:

7/1

Так как в конструкторе копирования (который C++ предоставит автоматически) значения по умолчанию для m_denominator не будет.

Правило: Избегайте использования копирующей инициализации при работе с классами, вместо неё используйте uniform инициализацию.

Другие применения копирующей инициализации


Когда вы передаёте или возвращаете объект класса по значению, то в этом процессе используется копирующая инициализация. Рассмотрим следующую программу:

Здесь функция makeNegative() принимает объект класса Drob по значению и возвращает его так же по значению. Результат выполнения программы выше:

Copy constructor worked here!
Copy constructor worked here!
-6/7

Первый вызов конструктора копирования выполнится при передаче sixSeven в качестве аргумента в параметр d функции makeNegative(). Второй вызов выполнится при возврате объекта из makeNegative() обратно в main(). Таким образом, объект sixSeven копируется дважды.

В примере выше компилятор не может проигнорировать использование конструктора копирования как в передаче аргумента по значению, так и в его возврате. Однако, в некоторых случаях, если аргумент или возвращаемое значение соответствуют определённым критериям, то компилятор может проигнорировать использование конструктора копирования. Например:

В этом случае компилятор, скорее всего, проигнорирует использование конструктора копирования, хоть объект x и возвращается по значению.

Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (26 оценок, среднее: 4,81 из 5)
Загрузка...

Комментариев: 2

  1. Аватар Валерий:

    Поддержу предыдущего оратора. И добавлю.
    Результат 7 получиться никак не может.
    Кто откусил вывод косой и знаменателя. Оператор << никак не меняется.
    Скорее всего речь идет о выводе 7/0.

  2. Аватар WJ:

    Немного не понятно, как следующий код:

    может выдать результат 7 в случае если не будет оптимизации?

    При вызове Drob(int, int) получим m_numerator = 7 и m_denominator = 1 в анонимном объекте, которые почленно скопируются дефолтным конструктором копирования в seven

Добавить комментарий

Ваш E-mail не будет опубликован. Обязательные поля помечены *