2014-01-18 2 views
4

В соответствии с Google style guidelines «Несколько классов должны быть скопированы. У большинства не должно быть ни конструктора копирования, ни оператора присваивания».Когда вы должны сделать класс неприступным?

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

Однако я слышал некоторые аргументы против этого:

  • Доступ ссылки (обычно) медленнее, чем доступ к значению.
  • В некоторых вычислениях я мог бы оставить исходный объект так, как он есть, и просто вернуть измененный объект.
  • Возможно, мне захочется сохранить значение вычисления в качестве локального объекта в функции и вернуть его, чего я не смог бы сделать, если бы вернул его по ссылке.
  • Если класс достаточно мал, передача по ссылке медленнее.

Каковы положительные/отрицательные стороны этого руководства? Существует ли стандартное «эмпирическое правило» для того, чтобы сделать классы недоступными? Что следует учитывать при создании новых классов?

+3

Да, я не согласен с Google там. –

+1

Два эмпирических правила: если ваш класс выражает уникальное право собственности, сделайте его незакрепленным. -> 'unique_ptr'. Если «копирование» не имеет никакого смысла для вашего класса, сделайте свой класс noncopyable -> 'mutex',' thread' – dyp

+1

Я не думаю, что руководство по стилю для C++ в целом, больше подходит для работы со своим устаревшим кодом на C++. –

ответ

6

У меня есть две проблемы с их советами:

  1. Это не относится к современным C++, игнорируя операторы Конструкторы/Переместить назначение, и поэтому предполагается, что принимает объекты по значению (которые скопировали ранее) часто неэффективен.

  2. Он не доверяет программисту, чтобы сделать правильную вещь и правильно разработать свой код. Вместо этого он ограничивает программиста, пока он не будет вынужден нарушить правило.

Независимо от того, должен ли ваш класс быть скопированным, подвижным, оба или ни одно из них не должно быть конструктивным решением, основанным на использовании самого класса. Например, std::unique_ptr - отличный пример класса, который должен быть только подвижным, поскольку копирование приведет к аннулированию всей его цели. Когда вы разрабатываете класс, спросите себя, имеет ли смысл его копировать. В большинстве случаев ответ будет да.

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

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

  1. Я собираюсь нужна копия этого объекта?
  2. Нужно ли изменить этот объект?
  3. Какова продолжительность жизни объекта?
  4. Является ли объект дополнительным?

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

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

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

+3

Я не рекомендую принимать ответ так рано в таком глубоком вопросе. Некоторые лучшие ответы могут занять некоторое время. –

+0

@ dyp Хорошая точка. Отредактировано немного немного. –

Смежные вопросы