Оператор присваивания C ++ - сгенерированный компилятором или пользовательский?

У меня есть средний сложный класс C ++, который содержит набор данных, считанных с диска. Он содержит эклектичную смесь поплавков, целых и структур и в настоящее время широко используется. Во время основного обзора кода был задан вопрос, есть ли у нас пользовательский оператор присваивания или мы полагаемся на сгенерированную компилятором версию, и если да, то как мы узнаем, что она работает правильно? Ну, мы не написали пользовательское назначение, и поэтому был добавлен модульный тест, чтобы проверить, что если мы сделаем:

CalibDataSet datasetA = getDataSet();
CalibDataSet dataSetB = datasetA;

, то datasetB совпадает с datasetA. Пара сотен строк или около того. Теперь заказчик заявляет, что мы не можем полагаться на корректность компилятора (gcc) для будущих выпусков, и мы должны написать свой собственный. Правильно ли они настаивать на этом?

Дополнительная информация:

Я впечатлен уже опубликованными ответами / комментариями и временем ответа. Другой способ задать этот вопрос может быть следующим: Когда структура / класс POD становится «не» структурой / классом POD?

9
задан ExpatEgghead 26 August 2010 в 06:17
поделиться

4 ответа

Хорошо известно, что будет делать автоматически сгенерированный оператор присваивания - это определено как часть стандарта, и компилятор C++, соответствующий стандартам, всегда будет генерировать корректно работающий оператор присваивания (если это не так, то это не будет компилятором, соответствующим стандартам).

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

14
ответ дан 4 December 2019 в 08:31
поделиться

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

1
ответ дан 4 December 2019 в 08:31
поделиться

Я предполагаю, что проблема мелкой копии может возникнуть, если вы имеете дело со строками. http://www.learncpp.com/cpp-tutorial/912-shallow-vs-deep-copying/

но я думаю, что всегда рекомендуется писать перегрузки присваивания для пользовательских классов.

0
ответ дан 4 December 2019 в 08:31
поделиться

Самой распространенной причиной явного определения оператора присваивания является поддержка "удаленного владения" - в основном класс, который включает один или несколько указателей и владеет ресурсами, на которые ссылаются эти указатели. В таком случае вам обычно нужно определить присваивание, копирование (т. е. конструктор копирования) и уничтожение. Для таких случаев существует три основных стратегии (отсортированные по убыванию частоты использования):

  1. Глубокое копирование
  2. Подсчет ссылок
  3. Передача права собственности

Глубокое копирование означает выделение нового ресурса для цели назначения/ копировать. Например, строковый класс имеет указатель на содержимое строки; когда вы назначаете его, назначение выделяет новый буфер для хранения нового содержимого в месте назначения и копирует данные из источника в буфер назначения. Это используется в большинстве текущих реализаций ряда стандартных классов, таких как std::string и std::vector.

Подсчет ссылок раньше также был довольно распространенным явлением.Многие (большинство?) старых реализаций std::string использовали подсчет ссылок. В этом случае вместо выделения и копирования данных для строки вы просто увеличиваете счетчик ссылок, чтобы указать количество строковых объектов, ссылающихся на конкретный буфер данных. Вы выделяли новый буфер только тогда, когда/если содержимое строки было изменено, поэтому оно должно было отличаться от других (т. е. использовалось копирование при записи). Однако при многопоточности вам необходимо синхронизировать доступ к счетчику ссылок, что часто оказывает серьезное влияние на производительность, поэтому в более новом коде это довольно необычно (в основном используется, когда что-то хранит столько данных, что оно того стоит. потенциально тратя немного процессорного времени, чтобы избежать такой копии).

Передача права собственности является относительно необычным явлением. Это то, что делает std::auto_ptr. Когда вы что-то назначаете или копируете, источник назначения/копии в основном уничтожается — данные передаются от одного к другому. Это (или может быть) полезно, но семантика достаточно отличается от обычного присваивания, что часто противоречит здравому смыслу. В то же время, при правильных обстоятельствах, он может обеспечить большую эффективность и простоту. C++0x сделает передачу права собственности более управляемой за счет добавления типа unique_ptr, который делает его более явным, а также добавления ссылок rvalue, упрощающих реализацию передачи права собственности для одного довольно большого класса ситуациях, когда это может повысить производительность без семантики, явно противоречащей здравому смыслу.

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

Даже если он каким-то образом был выпущен, ваша защита от него состояла бы в том, чтобы просто не использовать его. Нет никаких сомнений в том, что такой выпуск будет заменен в течение нескольких часов. С существующим проектом среднего или крупного размера вы в любом случае не захотите переключаться на компилятор до тех пор, пока он не станет широко использоваться какое-то время.

8
ответ дан 4 December 2019 в 08:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: