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

  Юрий  | 

  Обновл. 28 Сен 2020  | 

 14553

 ǀ   3 

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

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

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

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

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

7/1

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

А, как мы уже знаем из предыдущего урока, это может привести к вызову как 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 (89 оценок, среднее: 4,74 из 5)
Загрузка...

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

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

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

    1. Аватар Андрей:

      Да что-то и 7/0, наверное, никогда не получится. В случае конструктора копирования будет создан анонимный объект, конструктор для него знаменатель укажет 1 (по умолчанию), а потом конструктор копирования (компилятора) сделает присвоение из анонимного объекта каждому члену (числителю и знаменателю) для вновь создаваемого объекта .

  2. Аватар WJ:

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

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

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

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

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