Имеет ли смысл [C ++ 11: 12.8 / 7]? - PullRequest
4 голосов
/ 13 января 2012

[C++11: 12.8/7]: Если определение класса явно не объявляет конструктор копирования, он объявляется неявно. Если определение класса объявляет конструктор перемещения или оператор присваивания перемещения, неявно объявленный конструктор копирования определяется как удаленный; в противном случае он определяется как дефолтный (8.4) .Последний случай считается устаревшим, если у класса есть пользовательский оператор копирования или пользовательский деструктор.Таким образом, для определения класса

struct X {
   X(const X&, int);
};

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

X::X(const X& x, int i =0) { /* ... */ }

, то любое использование конструктора копирования X некорректно из-за неоднозначности ;Диагностика не требуется.

Для меня это не имеет большого смысла.

Как пример кода, представленный «Таким образом», имеет какое-либо отношение к «последнему»"случай, который я выделил курсивом?

Насколько я понимаю, пока:

  • Если определение класса не объявляет явно конструктор копирования, и
  • определение класса не объявляет конструктор перемещения или оператор присваивания перемещения, и
  • класс имеет объявленный пользователем оператор присваивания копии или объявленный пользователем деструктор, тогда
  • неявно -определенный конструктор копирования определен как default ed, и это устарело .

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

И какое отношение к этому имеет пример кода?Этот конструктор не является конструктором копирования, конструктором перемещения, оператором назначения перемещения, оператором назначения копирования или объявленным пользователем деструктором;это просто объявленный пользователем конструктор, нет?Где эта «двусмысленность»?

Может ли кто-нибудь расшифровать этот отрывок для меня?

Ответы [ 3 ]

3 голосов
/ 13 января 2012

Означает ли это, что наличие класса, удовлетворяющего этим трем условиям, устарело?

Да; если у вас есть оператор или деструктор, назначенный для копирования, вы должны также объявить конструктор копирования. По сути, это просто говорит о том, что ваш класс должен следовать правилу Три (или Пять, или как он называется в C ++ 11).

Это кажется странным само по себе, что стандартное поведение - на одном дыхании - не рекомендуется.

Поведение предписано стандартом, потому что это было поведение в C ++ 03 - изменение его нарушило бы унаследованный код. Так же, как стандарт определяет поведение (например) спецификаций динамических исключений, а также осуждает их.

Как пример кода, введенный словом «Таким образом», имеет какое-либо отношение к «последнему» случаю, который я выделил курсивом?

Это не имеет ничего общего с "последним" делом.

Это иллюстрация потенциальной проблемы, вызванной нормальным поведением, определенным в предложении: будет конфликт между неявно объявленным конструктором копирования и объявленным пользователем конструктором с аргументами по умолчанию, так что его можно вызывать как конструктор копирования.

Где эта "двусмысленность"?

Рассмотрим код:

X x1;  // assume there's also a default constructor
X x2(x);

Должен ли x2 быть инициализирован с помощью объявленного пользователем конструктора (со вторым аргументом, принимающим значение по умолчанию) или неявно объявленным конструктором копирования? Оба одинаково хорошо подходят для использования. Это двусмысленность.

3 голосов
/ 13 января 2012

Просто чтобы ответить на 2 часть.Неоднозначность обусловлена ​​параметром по умолчанию int i = 0, который позволяет вызывать этот конструктор только с первым аргументом const X& x, что позволяет использовать его и в качестве конструктора копирования, поскольку он совместим с сигнатурой X(const X& x)(§12.8 / 2 для точного текста).Это противоречит неявному конструктору копирования, таким образом, неоднозначность.

2 голосов
/ 13 января 2012

Похоже, проясняется роль конструктора перемещения и его влияние на конструктор копирования. Это говорит о том, что если вы объявите конструктор перемещения или оператор присваивания перемещения, то не будет неявного конструктора копирования. Если вы определили свой собственный конструктор копирования или оператор копирования, вы можете игнорировать бит, который вы поместили в полужирный текст.

Я думаю, что целью примера было показать, что для класса:

struct X {
   X(const X&, int);
};

Конструктор копирования определен неявно, поскольку пользовательский конструктор копирования не определен. Однако если вы предоставите значение по умолчанию для второго аргумента int (как они это сделали), то вызов:

X newX(oldX);

Может быть вызовом определяемого пользователем конструктора или конструктора копирования: об этой неоднозначности они говорят.

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