errore: utilizzo della funzione cancellata


122

Sto lavorando su un codice C ++ scritto da un amico e ricevo il seguente errore che non ho mai visto prima durante la compilazione con 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

Modifica: proviene da una parte del codice che utilizza boost MSM: Boost Webpage

Edit2: non è = delete()utilizzato da nessuna parte nel codice sorgente.

In generale, cosa significa questo errore? Cosa dovrei cercare quando si verifica questo tipo di errore?


4
e il codice che stai compilando?
ColWhi

Mi stavo solo chiedendo cosa significasse l'errore? Devo inserire il codice anche per quello?
navetta87

1
gcc.gnu.org/bugzilla/show_bug.cgi?id=47417 potrebbe aiutare, inoltre stai usando boost?
ColWhi

@Sasquiha, sì, sto usando Boost MSM.
navetta 87

20
Poiché si presenta come la prima corrispondenza di Google per questo tipo di errore, non è il caso qui, ma la causa più comune di questo tipo di errore è dopo aver aggiunto un costruttore personalizzato a una classe, di conseguenza il compilatore smette di creare il costruttore predefinito e se un'istanza della classe viene mai creata tramite il costruttore predefinito, viene visualizzato questo errore. Basta aggiungere il costruttore predefinito in modo esplicito.
SF.

Risposte:


171

Il messaggio di errore dice chiaramente che il costruttore predefinito è stato eliminato implicitamente . Dice anche perché: la classe contiene una variabile const non statica, che non verrebbe inizializzata dal ctor predefinito.

class X {
    const int x;
};

Poiché X::xè const, deve essere inizializzato, ma un ctor predefinito normalmente non lo inizializzerebbe (perché è un tipo POD). Pertanto, per ottenere un ctor predefinito, è necessario definirne uno da soli (e deve essere inizializzato x). Puoi ottenere lo stesso tipo di situazione con un membro che è un riferimento:

class X { 
    whatever &x;
};

Probabilmente vale la pena notare che entrambi disabiliteranno anche la creazione implicita di un operatore di assegnazione, essenzialmente per lo stesso motivo. L'operatore di assegnazione implicita normalmente esegue l'assegnazione in base ai membri, ma con un membro const o un membro di riferimento non può farlo perché il membro non può essere assegnato. Per far funzionare l'assegnazione, è necessario scrivere il proprio operatore di assegnazione.

Questo è il motivo per cui un constmembro dovrebbe in genere essere statico: quando si esegue un compito, non è comunque possibile assegnare il membro const. In un caso tipico tutte le tue istanze avranno lo stesso valore, quindi potrebbero anche condividere l'accesso a una singola variabile invece di avere molte copie di una variabile che avranno tutte lo stesso valore.

È possibile, ovviamente, creare istanze con valori diversi: tu (ad esempio) passi un valore quando crei l'oggetto, quindi due oggetti diversi possono avere due valori diversi. Se, tuttavia, provi a fare qualcosa come scambiarli, il membro const manterrà il suo valore originale invece di essere scambiato.


@ Jeffry Coffin: Il messaggio di errore effettivo è stato pubblicato come modifica, il messaggio di errore iniziale pubblicato era soloC++ error: use of deleted function
Alok Save

1
@Als: Scusa, probabilmente avrei dovuto essere esplicito sul fatto che non lo intendevo come un insulto o qualcosa di simile, solo che ciò che era attualmente disponibile rendeva evidente che quelle risposte non erano corrette.
Jerry Coffin

Nessun problema, non volevo essere irremovibile ... La tua risposta è fantastica e spiega al meglio la situazione. +1 da parte mia :)
Alok Save

Presumo che potrebbe essere in grado di aiutarmi con il mio problema qui per favore: stackoverflow.com/questions/23349524/...
Saher Ahwal

2
@ OllieFord: Dipende. Cosa dovrebbe accadere se (ad esempio) si assegna un oggetto con un valore in quel campo a un altro che ha un valore diverso in quel campo? Se deve essere sovrascritto, non può essere const. Se ciò non dovrebbe essere consentito, il valore potrebbe davvero essere parte del tipo (ad esempio, un parametro del modello, se noto in fase di compilazione).
Jerry Coffin

11

Stai utilizzando una funzione contrassegnata come deleted.
Per esempio:

int doSomething( int ) = delete;

= Delete è una nuova funzionalità di C ++ 0x. Significa che il compilatore dovrebbe interrompere immediatamente la compilazione e lamentarsi "questa funzione viene eliminata" una volta che l'utente usa tale funzione.

Se vedi questo errore, dovresti controllare la dichiarazione della funzione per =delete .

Per saperne di più su questa nuova funzionalità introdotta in C ++ 0x, controllare questo fuori.


7
Per curiosità, quando sarebbe utile fare qualcosa del genere?
Pepe

@Peter: per prevenire conversioni implicite.
R. Martinho Fernandes

7
In realtà dice "implicitamente cancellato perché ..." , l'esempio sopra sarebbe esplicito.
Georg Fritzsche

@Peter R: sembra che questo sia un esempio: en.wikipedia.org/wiki/…
shuttle87

1
@Downvoter: il messaggio di errore effettivo è stato pubblicato come modifica, il messaggio di errore iniziale pubblicato era soloC++ error: use of deleted function
Alok Save

4

gcc 4.6 supporta una nuova caratteristica delle funzioni eliminate, in cui puoi scrivere

hdealt() = delete;

per disabilitare il costruttore predefinito.

Qui il compilatore ha ovviamente visto che non è possibile generare un costruttore predefinito, e =deletelo fa per te.


2

Ho riscontrato questo errore durante l'ereditarietà da una classe astratta e non implementando tutti i metodi virtuali puri nella mia sottoclasse.


1
Allo stesso modo, ho ottenuto lo stesso derivando public virtualda una classe base di 2 ° livello in cui la classe base di 1 ° livello aveva un costruttore predefinito eliminato in modo esplicito. La rimozione ha virtualrisolto il problema senza dover implementare tutti i metodi.
Maitre Bart

1

Nell'attuale standard C ++ 0x puoi disabilitare esplicitamente i costruttori predefiniti con la sintassi di cancellazione, ad es

MyClass() = delete;

Gcc 4.6 è la prima versione a supportare questa sintassi, quindi forse questo è il problema ...


Gcc 4.6 is the first version to support this syntaxImmagino che questo spiegherebbe perché non l'ho mai visto prima poiché ho appena iniziato a usare gcc4.6 di recente.
navetta87

2
Uso questa sintassi con GCC 4.5 da anni. Intendo giorni.
R. Martinho Fernandes

Ah, devo aver pensato ai medici delegati che sono in GCC 4.6.
jarmond

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.