ошибка: использование удаленной функции

122

Я работал над некоторым кодом C ++, который написал мой друг, и при компиляции с gcc4.6 получаю следующую ошибку, которую никогда раньше не видел:

error: use of deleted function

GameFSM_<std::array<C, 2ul> >::hdealt::hdealt()’ is implicitly deleted because the default definition would be ill-formed:
uninitialized non-static const member const h_t FlopPokerGameFSM_<std::array<C, 2ul> >::hdealt::h

Изменить: это происходит из части кода с использованием boost MSM: Boost Webpage

Edit2: = delete()нигде в исходном коде не используется.

Вообще, что означает эта ошибка? Что мне следует искать при возникновении этого типа ошибки?

shuttle87
источник
4
а код, который вы компилируете?
ColWhi
Мне было больше просто интересно, что означает ошибка? Нужно ли мне публиковать код и для этого?
Shuttle87,
1
gcc.gnu.org/bugzilla/show_bug.cgi?id=47417 может помочь, вы также используете boost?
ColWhi
@Sasquiha, да, я использую Boost MSM.
Shuttle87
20
Поскольку это первое совпадение Google для этого типа ошибки - здесь не тот случай, но наиболее частая причина такого рода ошибок возникает после того, как вы добавили в класс некоторый настраиваемый конструктор - в результате компилятор перестает создавать конструктор по умолчанию , и если экземпляр класса когда-либо создается с помощью конструктора по умолчанию, появляется эта ошибка. Просто добавьте конструктор по умолчанию явно.
SF.

Ответы:

171

В сообщении об ошибке четко указано, что конструктор по умолчанию был удален неявно . Он даже говорит, почему: класс содержит нестатическую переменную const, которая не будет инициализирована ctor по умолчанию.

class X {
    const int x;
};

Поскольку он X::xесть const, он должен быть инициализирован, но ctor по умолчанию обычно не инициализирует его (потому что это тип POD). Следовательно, чтобы получить ctor по умолчанию, вам нужно определить его самостоятельно (и он должен инициализироваться x). Вы можете получить такую ​​же ситуацию с членом, который является ссылкой:

class X { 
    whatever &x;
};

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

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

Конечно, можно создавать экземпляры с разными значениями - вы (например) передаете значение при создании объекта, поэтому два разных объекта могут иметь два разных значения. Однако если вы попытаетесь сделать что-то вроде их замены, член const сохранит свое исходное значение вместо того, чтобы быть замененным.

Джерри Гроб
источник
@ Джеффри Коффин: Фактическое сообщение об ошибке было опубликовано как отредактированное, Первоначальное сообщение об ошибке было опубликовано толькоC++ error: use of deleted function
Alok Save
1
@Als: Извините, мне, наверное, следовало прямо сказать, что я не имел в виду это как оскорбление или что-то в этом роде, просто то, что было доступно в настоящее время, показало, что эти ответы были неправильными.
Джерри Коффин
Нет проблем, я не хотел быть непреклонным ... Ваш ответ фантастический и лучше всего объясняет ситуацию. +1 от меня :)
Alok Save
Я предполагаю, что вы могли бы помочь мне с моей проблемой здесь, пожалуйста: stackoverflow.com/questions/23349524/…
Saher Ahwal
2
@OllieFord: Это зависит от обстоятельств. Что должно произойти, если (например) вы назначите объект с одним значением в этом поле другому, имеющему другое значение в этом поле? Если он должен быть перезаписан, он не может быть const. Если это вообще не должно быть разрешено, тогда значение действительно может быть частью типа (например, параметр шаблона, если он известен во время компиляции).
Джерри Коффин
11

Вы используете функцию, отмеченную как deleted.
Например:

int doSomething( int ) = delete;

Знак = delete - это новая функция C ++ 0x. Это означает, что компилятор должен немедленно прекратить компиляцию и пожаловаться на то, что «эта функция удалена», как только пользователь использует такую ​​функцию.

Если вы видите эту ошибку, вам следует проверить объявление функции для =delete.

Чтобы узнать больше об этой новой функции, представленной в C ++ 0x, посмотрите это .

Алок Сохранить
источник
7
Из любопытства, когда подобное может быть полезно?
Пепе
@Peter: для предотвращения неявных преобразований.
Р. Мартиньо Фернандес
7
На самом деле он говорит «неявно удалено, потому что ...» , приведенный выше пример будет явным.
Георг Фриче
@Peter R: похоже, это пример: en.wikipedia.org/wiki/…
шаттл87
1
@Downvoter: фактическое сообщение об ошибке было опубликовано как отредактированное, опубликовано только исходное сообщение об ошибкеC++ error: use of deleted function
Alok Save
4

gcc 4.6 поддерживает новую функцию удаленных функций, где вы можете написать

hdealt() = delete;

чтобы отключить конструктор по умолчанию.

Здесь компилятор, очевидно, увидел, что конструктор по умолчанию не может быть сгенерирован, и сделал =deleteэто за вас.

Бо Перссон
источник
2

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

Кристофер
источник
1
Точно так же я получил то же самое, унаследовав public virtualот базового класса 2-го уровня, где базовый класс 1-го уровня имел явно удаленный конструктор по умолчанию. Удаление virtualустранило проблему, не применяя все методы.
Мэтр Барт,
1

В текущем стандарте C ++ 0x вы можете явно отключить конструкторы по умолчанию с помощью синтаксиса удаления, например

MyClass() = delete;

Gcc 4.6 - первая версия, поддерживающая этот синтаксис, так что, возможно, проблема в этом ...

jarmond
источник
Gcc 4.6 is the first version to support this syntaxДумаю, это объясняет, почему я никогда не видел его раньше, поскольку недавно начал использовать gcc4.6.
шаттл87,
2
Я использую этот синтаксис с GCC 4.5 в течение многих лет. Я имею в виду дни.
R. Martinho Fernandes
Ах, я, должно быть, думал о делегированных ctors, которые есть в GCC 4.6.
jarmond
1

Переход с gcc 4.6 на gcc 4.8 решил эту проблему.

Майкл Босуорт
источник