Является ли хорошей практикой вообще делать тяжелые классы не копируемыми? - PullRequest
1 голос
/ 19 марта 2010

У меня есть класс Shape, содержащий потенциально много вершин, и я собирался сделать конструктор копирования / назначение копирования частным, чтобы предотвратить случайное ненужное копирование моего тяжеловесного класса (например, передавая по значению, а не по ссылке). *

Чтобы сделать копию Shape, нужно сознательно вызвать метод «клон» или «дубликат».

Это хорошая практика? Интересно, почему контейнеры STL не используют этот подход, так как я редко хочу передавать их по значению.

Ответы [ 5 ]

7 голосов
/ 19 марта 2010

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

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

4 голосов
/ 19 марта 2010

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

Обратите внимание, что вектор, строка, карта, список и т. Д. STL могут по-разному считаться «тяжеловесными» объектами (особенно что-то вроде вектора с 10000 элементов!). Все эти классы все еще предоставляют конструкторы копирования и операторы присваивания, поэтому, если вы знаете, что делаете (например, создаете список векторов std ::), вы можете при необходимости скопировать их.

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

4 голосов
/ 19 марта 2010

Как правило, вы не делаете классы недоступными для копирования только потому, что они тяжелые (вы показали хороший пример STL).

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

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

Небольшая заметка о clone() - используется как конструктор полиморфных копий - имеет разные значение и используется по-разному.

4 голосов
/ 19 марта 2010

ИМХО, предоставление конструктора копирования и оператора присваивания или не зависит больше от того, что моделирует ваш класс, чем от стоимости копирования.

Если ваш класс представляет значения , то есть если передача объекта или копии объекта не имеет значения, то предоставьте их (и предоставьте также оператор равенства)

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

Иногда есть классы, которые вы не можете легко классифицировать. Контейнеры находятся в этом положении. Это означает, что следует рассматривать их как объекты и передавать их только по ссылке и выполнять специальные операции для создания копии при необходимости. Вы также можете рассматривать их просто как совокупность значений, поэтому копирование имеет смысл. STL был разработан вокруг типов значений. И поскольку все является ценностью, для контейнеров имеет смысл быть таковыми. Это позволяет такие вещи, как map<int, list<> >, которые являются полезными. (Помните, что вы не можете помещать классы без копий в контейнер STL).

2 голосов
/ 19 марта 2010

В зависимости от ваших потребностей ...

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

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

...