Почему конструктор не по умолчанию НЕ рассматривается в правиле трех? - PullRequest
1 голос
/ 06 октября 2011

Правило трех (также известное как Закон Большой Тройки или Большой Тройки) - это практическое правило в C ++, которое утверждает, что если класс определяет одно из следующего, он, вероятно, должен явно определять все три: деструктор, конструктор копирования, оператор присвоения копии.

Почему конструктор не по умолчанию не считается одним из них? Когда в классе есть какой-либо ресурс, программист должен все равно определить конструктор не по умолчанию.

Ответы [ 4 ]

8 голосов
/ 06 октября 2011

Почему конструктор не по умолчанию не считается одним из них?Когда в классе есть какой-либо ресурс, программист должен все равно определить конструктор не по умолчанию.

Это не обязательно верно.Конструктор может не aquire любой ресурс.Другие функции также могут aquire .Фактически, может быть много функций (включая конструкторы ), которые могут aquire ресурсы.Например, в случае std::vector<T> это resize() и reserve(), которые aquire ресурсы.Так что думайте о конструкторе (ах) точно так же, как о других функциях, которые могут привлекать ресурсы.

Идея этого правила заключается в том, что когда вы делаете копию, генерируется код по умолчанию для копированиякомпилятором не сработает.Следовательно, вам нужно написать семантическую копию самостоятельно.И поскольку класс управляет ресурсами (не имеет значения, какие функции aquire it), деструктор должен release it, потому что деструктор гарантированно будет выполнен дляполностью построенный объект.Следовательно, вы также должны определить деструктор.И в C ++ 11 вы также должны реализовать семантику перемещения.Логический аргумент для семантики перемещения аналогичен аргументу семантики копирования, за исключением того, что в семантике движения вы также изменили источник .Семантика движения очень похожа на донорство органов;когда вы отдаете свой орган другому, вы больше не владеете им.

2 голосов
/ 06 октября 2011

Это не то, к чему относится правило трех.

Любой класс, который управляет ресурсами, будет иметь этот деструктор, и, следовательно, правило трех применяется в любом случае . Дело в том, что вам абсолютно не нужны конструкторы не по умолчанию, а вам do нужны другие (конструктор копирования / оператор присваивания).

По крайней мере, это было жизненно важно, например, для элементы в стандартных контейнерах.

Теперь с семантикой перемещения (c ++ 11) все начинает немного меняться. Будет ли правило 5? Я не знаю, как это получится с точки зрения «лучших практик» и «практических правил».

Фактически можно уже сформулировать вариацию правила три: класс, который определяет деструктор, должен также определять конструктор копирования / перемещения и оператор присваивания копирования / перемещения. И если определен конструктор копирования, также должен быть определен оператор присваивания копии. И если определен конструктор перемещения, также должен быть определен оператор присваивания перемещения.

В любом случае, это будет мое эмпирическое правило.

0 голосов
/ 06 октября 2011

Определение конструктора не по умолчанию автоматически не означает, что вам нужен деструктор и т. Д. - вы можете просто использовать этот конструктор для удобства заполнения типа POD.

Тем не менее, то же самое относится и к конструкторам по умолчанию.

По сути, "вам нужна большая тройка?" срабатывает, когда класс будет управлять ресурсом. Вам все еще может не понадобиться конструктор по умолчанию, но вам do нужен конструктор для установки действительного начального состояния.

Это вновь созданное состояние может еще не владеть экземпляром ресурса, но если это не так, то оно должно знать, что оно не имеет (например, имеет нулевой указатель).

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

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

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

0 голосов
/ 06 октября 2011

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

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

...