Правильно ли использовать объявление только для пустых приватных конструкторов в C ++? - PullRequest
4 голосов
/ 13 ноября 2009

Например, это правильно:

class C 
{
   private: 
     C();
     C(const & C other);
}

или лучше дать определение (я):

class C 
{
   private: 
     C() {};
     C(const & C other) {};
}

? Спасибо за текущие ответы. Давайте расширим этот вопрос - генерирует ли компилятор лучший код в одном из этих примеров? Я могу представить, что предоставление тела для ctor заставляет компилятор включать некоторый (пустой) код в модуль компиляции? Это также верно для автоматически сгенерированного кода?

Ответы [ 8 ]

11 голосов
/ 13 ноября 2009

Если вы не хотите, чтобы ваш объект был копируемым, тогда нет необходимости предоставлять реализацию. Просто объявите копию ctor частной без какой-либо реализации. То же самое относится и к другим ctors, если вы не хотите, чтобы какое-либо тело использовало их, просто объявите их закрытыми без какой-либо реализации.

9 голосов
/ 13 ноября 2009

Хорошо, если вы их не используете.

Стандарт 0x позволяет использовать удаленные функции .

class X {
   // ...
   X& operator=(const X&) = delete; // Disallow copying
   X(const X&) = delete;
};
5 голосов
/ 13 ноября 2009

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

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

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

2 голосов
/ 13 ноября 2009

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

Однако, ошибка компилятора была бы предпочтительнее, так как вы узнаете об ошибке быстрее. Для этого есть boost::noncopyable, или вы можете наследовать от базового класса, который скрывает его конструктор копирования и оператор присваивания.

Относительно конструктора по умолчанию: компилятор не сгенерирует его, если вы вообще объявите какой-либо конструктор. Как правило, нет необходимости скрывать это.

2 голосов
/ 13 ноября 2009

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

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

0 голосов
/ 13 ноября 2009

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

0 голосов
/ 13 ноября 2009

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

0 голосов
/ 13 ноября 2009

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

...