błąd: użycie usuniętej funkcji

121

Pracowałem nad kodem w C ++ napisanym przez znajomego i otrzymuję następujący błąd, którego nigdy wcześniej nie widziałem podczas kompilacji z 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

Edycja: pochodzi z części kodu używającej strony internetowej boost MSM: Boost

Edit2: nie jest = delete()nigdzie używany w kodzie źródłowym.

Co ogólnie oznacza ten błąd? Czego powinienem szukać, gdy wystąpi tego typu błąd?

czółenko 87
źródło
4
i kod, który kompilujesz?
ColWhi
Bardziej zastanawiałem się, co oznacza błąd? Czy muszę również wysłać kod?
transfer 87
1
gcc.gnu.org/bugzilla/show_bug.cgi?id=47417 może pomóc, czy też używasz przyspieszenia?
ColWhi
@Sasquiha, tak, używam boost MSM.
transfer 87
20
Ponieważ pojawia się to jako pierwsze dopasowanie Google dla tego typu błędu - nie w tym przypadku, ale najczęstszą przyczyną tego rodzaju błędu jest dodanie niestandardowego konstruktora do klasy - w rezultacie kompilator przestaje tworzyć domyślny konstruktor i jeśli wystąpienie klasy zostanie kiedykolwiek utworzone za pomocą domyślnego konstruktora, pojawi się ten błąd. Po prostu dodaj jawnie domyślny konstruktor.
SF.

Odpowiedzi:

170

Komunikat o błędzie wyraźnie mówi, że domyślny konstruktor został niejawnie usunięty . Mówi nawet dlaczego: klasa zawiera niestatyczną zmienną const, która nie została zainicjowana przez domyślny ctor.

class X {
    const int x;
};

Ponieważ X::xjest const, musi zostać zainicjowany - ale domyślny ctor normalnie nie zainicjowałby go (ponieważ jest to typ POD). Dlatego, aby uzyskać domyślny ctor, musisz sam go zdefiniować (i musi on zostać zainicjowany x). Możesz mieć taką samą sytuację z członkiem, który jest odniesieniem:

class X { 
    whatever &x;
};

Prawdopodobnie warto zauważyć, że oba te elementy również wyłączą niejawne tworzenie operatora przypisania, zasadniczo z tego samego powodu. Niejawny operator przypisania zwykle wykonuje przypisanie składowe, ale w przypadku elementu członkowskiego stałego lub elementu referencyjnego nie może tego zrobić, ponieważ nie można przypisać elementu członkowskiego. Aby przypisanie zadziałało, musisz napisać własny operator przypisania.

Właśnie dlatego element constczłonkowski powinien być zwykle statyczny - kiedy wykonujesz przypisanie, i tak nie możesz przypisać stałego członka. W typowym przypadku wszystkie Twoje instancje będą miały tę samą wartość, więc równie dobrze mogą mieć dostęp do pojedynczej zmiennej zamiast mieć wiele kopii zmiennej, która będzie miała tę samą wartość.

Oczywiście możliwe jest jednak tworzenie instancji z różnymi wartościami - na przykład przekazujesz wartość podczas tworzenia obiektu, więc dwa różne obiekty mogą mieć dwie różne wartości. Jeśli jednak spróbujesz zrobić coś takiego jak zamiana ich, stała składowa zachowa swoją oryginalną wartość zamiast być zamieniona.

Jerry Coffin
źródło
@Jeffry Coffin: Rzeczywisty komunikat o błędzie został opublikowany jako zmiana, opublikowano tylko początkowy komunikat o błędzieC++ error: use of deleted function
Alok Save
1
@Als: Przepraszam, prawdopodobnie powinienem był wyraźnie powiedzieć, że nie zamierzałem tego jako zniewagi lub czegokolwiek w tym zamówieniu, tylko to, co było obecnie dostępne, pokazało, że te odpowiedzi nie były prawidłowe.
Jerry Coffin
Żadnych problemów, nie chciałem być nieugięty ... Twoja odpowiedź jest fantastyczna i najlepiej wyjaśnia sytuację. +1 ode mnie :)
Alok Zapisz
Zakładam, że możesz mi pomóc rozwiązać mój problem tutaj: stackoverflow.com/questions/23349524/…
Saher Ahwal
2
@OllieFord: To zależy. Co się stanie, jeśli (na przykład) przypiszesz obiekt z jedną wartością w tym polu do innego, który ma inną wartość w tym polu? Jeśli ma zostać nadpisany, nie może być const. Jeśli w ogóle nie powinno to być dozwolone, to wartość może naprawdę być częścią typu (np. Parametr szablonu, jeśli jest znany w czasie kompilacji).
Jerry Coffin
11

Używasz funkcji oznaczonej jako deleted.
Na przykład:

int doSomething( int ) = delete;

= Delete to nowa funkcja języka C ++ 0x. Oznacza to, że kompilator powinien natychmiast przerwać kompilację i narzekać „ta funkcja została usunięta”, gdy użytkownik jej użyje.

Jeśli widzisz ten błąd, sprawdź deklarację funkcji dla =delete.

Aby dowiedzieć się więcej o tej nowej funkcji wprowadzonej w C ++ 0x, sprawdź to .

Alok Save
źródło
7
Z ciekawości, kiedy zrobienie czegoś takiego byłoby pomocne?
Pepe
@Peter: aby zapobiec niejawnym konwersjom.
R. Martinho Fernandes
7
W rzeczywistości jest napisane „niejawnie usunięte, ponieważ ...” , powyższy przykład byłby wyraźny.
Georg Fritzsche
@Peter R: wygląda na to, że to jest przykład: en.wikipedia.org/wiki/…
transfer87
1
@Downvoter: Rzeczywisty komunikat o błędzie został opublikowany jako zmiana, opublikowano tylko początkowy komunikat o błędzieC++ error: use of deleted function
Alok Save
4

gcc 4.6 obsługuje nową funkcję usuniętych funkcji, w których można pisać

hdealt() = delete;

aby wyłączyć domyślny konstruktor.

W tym przypadku kompilator najwyraźniej zauważył, że nie można wygenerować domyślnego konstruktora i =deletezrobi to za Ciebie.

Bo Persson
źródło
2

Napotkałem ten błąd podczas dziedziczenia z klasy abstrakcyjnej i nie implementowania wszystkich czystych metod wirtualnych w mojej podklasie.

Krzysztof
źródło
1
Podobnie, otrzymałem to samo, wyprowadzając public virtualz klasy bazowej drugiego poziomu, w której klasa podstawowa pierwszego poziomu miała jawnie usunięty domyślny konstruktor. Usunięcie virtualrozwiązało problem bez konieczności wdrażania wszystkich metod.
Maitre Bart
1

W obecnym standardzie C ++ 0x można jawnie wyłączyć domyślne konstruktory za pomocą składni delete, np

MyClass() = delete;

Gcc 4.6 jest pierwszą wersją obsługującą tę składnię, więc może to jest problem ...

jarmond
źródło
Gcc 4.6 is the first version to support this syntaxMyślę, że to wyjaśniałoby, dlaczego nigdy wcześniej go nie widziałem, ponieważ niedawno zacząłem używać gcc4.6.
transfer 87
2
Używam tej składni w GCC 4.5 od lat. Mam na myśli dni.
R. Martinho Fernandes
Ach, musiałem myśleć o lekarzach delegowanych, którzy są w GCC 4.6.
jarmond
1

Przejście z gcc 4.6 na gcc 4.8 rozwiązało ten problem.

Michael Bosworth
źródło