Когда / зачем мне явно удалять конструктор? Если предположить, что причина в том, чтобы предотвратить его использование, почему бы просто не сделать это private?
Это вроде как хорошо сочетается = default, даже класс не может его использовать, и я лично предпочитаю видеть использование удаленной функции. над Функция является частной. В первом прямо говорится: «Это не предназначено для использования». Если из этого что-то выходит, класс, неспособный использовать это, фактически имеет семантическую разницу.
Крис
16
Честно говоря, я думаю, что люди начинают агрессию с закрытыми голосами. Я не понимаю, насколько это неконструктивно.
Лучиан Григоре 01
4
@LuchianGrigore: Согласен. Мне было интересно, почему сообщество стало таким жестким. Я не вижу в этом смысла.
Эд С.
11
Поскольку я редко использую C ++ 11, это для меня более информативно, чем, вероятно, даже понимает OP. Я даже не знал, что вы можете пометить конструктор для delete. И вопрос, и ответ Лучиана легко квалифицировать как конструктивные. Любой, кто не вдыхает тонкости C ++ 11, но скоро должен будет получить кое-что из обоих.
Это в принципе разные вещи. privateсообщает вам, что только члены класса могут вызывать этот метод или обращаться к этой переменной (или, конечно, друзьям). В этом случае для staticметода этого класса (или любого другого члена) допустимо вызывать privateконструктор класса. Это не относится к удаленным конструкторам.
Вам вообще не нужно объявлять Foo (), если вы объявляете Foo (int). Foo () не будет сгенерирован, поэтому Foo f в любом случае недействителен. Таким образом, ваш пример не показывает случай удаленного конструктора. Убедитесь
отметьте
1
@mark Я написал 2 конструктора, чтобы доказать это. Отредактирую, чтобы всем было понятно.
Лучиан Григоре 01
1
Я понимаю разницу, я просто не понимаю добавленную стоимость оператора удаления в целом и для конструктора в частности. В конце концов, я мог бы указать частный конструктор по умолчанию без тела. Тогда и код тоже выходит из строя, только при линковке. Что ж, я вижу, что удаление более явно передает намерение, но это все.
отметьте
11
@mark Да, это был бы способ работы C ++ 98. Но ИМХО, четкая передача намерения на самом деле очень важная вещь в программировании в целом. В этом случае некоторые читатели могут увидеть частный неопределенный конструктор и предположить, что он случайный, и просто добавить для него определение, особенно если определение столь же тривиально, как и конструктор по умолчанию (да, наличие комментария помогает, но мы бы предпочли компилятор -принуждение к принуждению к комментарию). Имея более четкое представление о намерениях, мы также получаем гораздо лучшее сообщение об ошибке, в котором говорится «явно удалено», а не «неопределенная ссылка».
mpark 05
2
Честно говоря, не понимаю, как это отвечает на главный вопрос. Вопрос в заголовке и первый вопрос OP в сообщении был: когда и почему я должен явно удалить свой конструктор?
Александр Болинский
13
зачем явно удалять конструктор?
Другая причина:
я использую, deleteкогда хочу убедиться, что класс вызывается с инициализатором. Я считаю это очень элегантным способом добиться этого без проверок во время выполнения.
Удаленная декларация здесь не нужна. Он автоматически удаляется любым конструктором, предоставленным пользователем
Майк Луи
5
Чтобы прояснить комментарий @MikeLui, удаленное объявление не нужно компилятору . Существует множество случаев, когда подобный код следует включать, чтобы заявить о своем намерении другим программистам .
Джефф Джи
Наряду с объявлением вашего намерения, он создает очевидное место для документирования вашей причины его удаления в общедоступном интерфейсе, и, кроме того, ошибка компилятора будет чем-то коротким, например «использование удаленной функции». Если бы Fooбыло несколько конструкторов, а не конструкторов по умолчанию, Foo foo;это вызвало бы гораздо более длинную ошибку, в которой перечислялись бы все неявно определенные, защищенные и частные конструкторы, которым не удалось сопоставить.
сигма
Я до сих пор не понимаю, как дополнительная строка с объявлением конструктора, в котором ключевое слово "= delete" декларирует намерение "без конструктора по умолчанию" лучше, чем ... просто без конструктора по умолчанию? Пример: я не хочу объявлять переменную «a» в моем коде - что лучше, написать «// int a; // не нужно определять переменную a» или просто ничего не писать об этой переменной в коде?
Еж
2
Я встречал ctors по умолчанию, объявленные как «удаленные» в исходном коде LLVM (например, в AlignOf.h). Связанные шаблоны классов обычно находятся в специальном пространстве имен, называемом 'llvm :: detail'. Я думаю, вся цель заключалась в том, что они рассматривали этот класс только как вспомогательный. Они никогда не собирались создавать их экземпляры; только для использования их в контексте других шаблонов классов с некоторыми уловками метапрограммирования, которые выполняются во время компиляции.
Например. есть этот шаблон класса AlignmentCalcImpl, который используется только в другом шаблоне класса с именем AlignOf в качестве параметра для оператора sizeof (.). Это выражение можно вычислить во время компиляции; и нет необходимости создавать экземпляр шаблона -> так почему бы не объявить удаление ctor по умолчанию, чтобы выразить это намерение.
= default
, даже класс не может его использовать, и я лично предпочитаю видеть использование удаленной функции. над Функция является частной. В первом прямо говорится: «Это не предназначено для использования». Если из этого что-то выходит, класс, неспособный использовать это, фактически имеет семантическую разницу.delete
. И вопрос, и ответ Лучиана легко квалифицировать как конструктивные. Любой, кто не вдыхает тонкости C ++ 11, но скоро должен будет получить кое-что из обоих.Ответы:
Как насчет:
//deleted constructor class Foo { public: Foo() = delete; public: static void foo(); }; void Foo::foo() { Foo f; //illegal }
против
//private constructor class Foo { private: Foo() {} public: static void foo(); }; void Foo::foo() { Foo f; //legal }
Это в принципе разные вещи.
private
сообщает вам, что только члены класса могут вызывать этот метод или обращаться к этой переменной (или, конечно, друзьям). В этом случае дляstatic
метода этого класса (или любого другого члена) допустимо вызыватьprivate
конструктор класса. Это не относится к удаленным конструкторам.Образец здесь .
источник
зачем явно удалять конструктор?
Другая причина:
я использую,
delete
когда хочу убедиться, что класс вызывается с инициализатором. Я считаю это очень элегантным способом добиться этого без проверок во время выполнения.Компилятор C ++ выполнит эту проверку за вас.
class Foo { public: Foo() = delete; Foo(int bar) : m_bar(bar) {}; private: int m_bar; }
Этот - очень упрощенный - код гарантирует, что такого экземпляра не существует:
Foo foo;
источник
Foo
было несколько конструкторов, а не конструкторов по умолчанию,Foo foo;
это вызвало бы гораздо более длинную ошибку, в которой перечислялись бы все неявно определенные, защищенные и частные конструкторы, которым не удалось сопоставить.Я встречал ctors по умолчанию, объявленные как «удаленные» в исходном коде LLVM (например, в AlignOf.h). Связанные шаблоны классов обычно находятся в специальном пространстве имен, называемом 'llvm :: detail'. Я думаю, вся цель заключалась в том, что они рассматривали этот класс только как вспомогательный. Они никогда не собирались создавать их экземпляры; только для использования их в контексте других шаблонов классов с некоторыми уловками метапрограммирования, которые выполняются во время компиляции.
Например. есть этот шаблон класса AlignmentCalcImpl, который используется только в другом шаблоне класса с именем AlignOf в качестве параметра для оператора sizeof (.). Это выражение можно вычислить во время компиляции; и нет необходимости создавать экземпляр шаблона -> так почему бы не объявить удаление ctor по умолчанию, чтобы выразить это намерение.
Но это только мое предположение.
источник