2010-08-06 2 views
7
#undef GOOGLE_DISALLOW_EVIL_CONSTRUCTORS 
#define GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeName) \ 
    TypeName(const TypeName&);       \ 
    void operator=(const TypeName&) 

Я читаю открытый исходный код из Google. Зачем копировать конструктор и оператор присваивания запрещены?Зачем копировать конструктор и оператор присваивания запрещены?

+1

Они называются «конструктор копирования» и «оператор присваивания». Нет такой конструкции, как конструктор присваивания. – Sjoerd

+2

Я бы назвал их «конструктором» и «оператором присваивания» или «конструктором копирования» и «оператором присваивания копий». –

+2

Я бы не назвал ЗЛО, что-то вроде их плохого цвета. Просто отключите их, например, boost: boost :: noncopyable –

ответ

12

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

+0

Прекрасный пример. Как я хочу, чтобы они это разрешили :) !!!! – DumbCoder

+0

+1 .... @ DumbCoder, если бы вы были кодером для программного обеспечения этого банка, это было бы возможно! – KedarX

+0

@Neil Butterworth: Почему бы просто не использовать синглтон вместо этого? – MainID

1

Если ваш тип содержит указатель или ссылочные элементы или не содержит семантического смысла для его копирования (например, он имеет дескриптор ресурса, который должен быть освобожден в деструкторе), то хорошей практикой является отключение конструктора копирования и оператор присваивания. В C++ 0x (например, в g ++ 4.4 или новее в режиме -std = C++ 0x) вы можете объявить их удаленными. В старых компиляторах вы просто объявляете их частными и нереализованными.

7

Проблема с конструктором копирования и оператором копирования-присваивания заключается в том, что компилятор автоматически генерирует реализации, если они явно не объявлены.

Это может привести к непредвиденным проблемам. Если класс имеет нетривиальный деструктор, он почти всегда должен предоставлять свои собственные реализации для конструктора копирования и оператора присваивания копий (это Law of the Big Three), поскольку созданные по умолчанию компиляторы, как правило, будут делать неправильные вещи.

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

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

+4

Это становится «Законом Большой пятерки» с предстоящим стандартным C++ 0x с добавлением Move Constructor/Assignment! – David

+1

@David: Оператор move/move-assign будет отключен (компилятор не будет генерировать их для вас, если вы их опустите). – jamesdlin

+0

Вы правы, но если вы заботитесь о производительности, вы тоже их предоставите. – David

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