Конструкторы копирования и оператор присваивания в C ++ - PullRequest
0 голосов
/ 01 марта 2020

Когда я изучал конструкторы на C ++, я придумывал вещи, которые мне трудно полностью понять. Во-первых, когда мы создаем объект класса (скажем, class Point), если мы не написали конструктор для себя, вызывается конструктор по умолчанию (я думаю, что для конструктора копирования)

Point p2 = p1;

Я получаю, что в этой ситуации вызывается конструктор копирования по умолчанию, но что, если я это сделаю:

Point p1;
p1.setX(3);
p2.setY(2);

Point p2;

p2 = p1;

Это все еще работает, но я предполагаю, что конструктор копирования по умолчанию здесь не вызывается, потому что я думаю, конструктор вызывается при создании объекта. Так как же это назначение работает во втором случае?

Кроме этого, мне было интересно, когда мы пишем наши собственные конструкторы копирования (ClassName (const ClassName &old_obj); или около того). Есть ли разница между двумя примерами ниже или это просто syntacti c sugar?

Point p3(p1);

и

Point p3 = p1;

И во втором примере, почему программа делает вывод, что мы передают p1 в качестве аргумента для копирования конструктора, в то время как мы не записали его после p3 внутри паратезов?

Кроме того, когда мы создаем объект класса, который принимает аргументы для его конструктора, мы используем круглые скобки для передачи данных в качестве аргументов. Но когда дело доходит до конструктора по умолчанию (, даже если мы написали свой собственный ), мы вообще не используем скобки и создаем объект так:

Point p1;

и не так:

Point p1(); // even if we defined our default constructor like "Point() {}"

В чем причина? Программа знает не создавать конструктор по умолчанию для нас?

1 Ответ

1 голос
/ 01 марта 2020

Я предполагаю, что реализация Point по умолчанию здесь.

Когда я изучал конструкторы в C ++, я обнаружил вещи, которые мне трудно понять полностью. Во-первых, когда мы создаем объект класса (скажем, класс Point), если мы не написали конструктор для себя, вызывается конструктор по умолчанию (я думаю, то же самое для конструктора копирования)

Point p2 = p1;

Я получаю, что в этой ситуации вызывается конструктор копирования по умолчанию, но что, если я это сделаю:

True

Point p1; p1.setX (3); p2.setY (2);

Точка p2;

p2 = p1; Это все еще работает, но я предполагаю, что конструктор копирования по умолчанию здесь не вызывается, потому что я думаю, что конструктор вызывается при создании объекта. Так как же это назначение работает во втором случае?

True. Используется оператор присваивания. Конструктор копирования используется только при создании нового объекта Point. На практике, если у вас есть конструктор копирования, у вас должен быть оператор назначения копирования с реализацией обработки.

Кроме этого, мне было интересно, когда мы пишем наши собственные конструкторы копирования (ClassName (const ClassName & old_obj) ); или так). Есть ли разница между двумя примерами ниже или это просто syntacti c sugar?

Вы бы написали свой собственный конструктор копирования, если в этом есть что-то особенное. Возможно, член не должен быть скопирован по какой-либо причине. Возможно, член не может быть скопирован с помощью конструктора копирования / конструктора присваивания, и вам нужно вызвать нестандартный метод CloneThis. Если все члены являются копируемыми, и все члены должны быть скопированы, просто используйте = default.

(я оставлю конструкцию перемещения / перемещения из этого)

Точка p3 (p1) ; и

Точка p3 = p1; И во втором примере, почему программа делает вывод, что мы передаем p1 в качестве аргумента для конструктора копирования, в то время как мы не записываем его после p3 внутри парантезов?

Начиная с C ++ 11, она гарантированно будет syntacti c сахара. Они оба гарантированно вызывают конструктор копирования. Альтернативная интерпретация заключается в том, чтобы сначала вызвать конструктор по умолчанию для p3, а затем вызвать оператор присваивания, чтобы присвоить значения от p1 до p3. Это явно расточительно и даже невозможно, если p3 не конструируется по умолчанию.

Кроме того, когда мы создаем объект класса, который принимает аргументы для его конструктора, мы используем скобки для передачи данных. в качестве аргументов. Но когда дело доходит до конструктора по умолчанию (даже если мы написали наш собственный), мы вообще не используем скобки и создаем такой объект:

Point p1; и не так:

Точка p1 (); // даже если мы определили наш конструктор по умолчанию как «Point () {}» В чем причина? Программа знает, не создавать ли нам конструктор по умолчанию?

Вы можете написать Point p1; или вы можете написать Point p1 {};

Вы можете написать Point p1 (), но это означает объявление функции p1 без аргументов, которая возвращает Point. Однако современные компиляторы предупредят вас о третьем варианте, потому что это распространенная ошибка.

Современная рекомендация - использовать {}, потому что он более однороден. Точка p1 {}; Точка p2 {1, 1};

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...