error: uso de función eliminada


121

He estado trabajando en un código C ++ que ha escrito un amigo y obtengo el siguiente error que nunca antes había visto al compilar 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

Editar: Esto proviene de una parte del código que usa boost MSM: Boost Webpage

Edit2: No se = delete()utiliza en ninguna parte del código fuente.

En términos generales, ¿qué significa este error? ¿Qué debo buscar cuando se produce este tipo de error?


4
y el código que estás compilando?
ColWhi

Más solo me preguntaba qué significaba el error. ¿Necesito publicar el código para eso también?
traslado 87

1
gcc.gnu.org/bugzilla/show_bug.cgi?id=47417 podría ayudar, ¿también estás usando boost?
ColWhi

@Sasquiha, sí, estoy usando boost MSM.
traslado 87

20
Dado que esto aparece como la primera coincidencia de Google para este tipo de error, no es el caso aquí, pero la causa más común para este tipo de error es después de que agregaste un constructor personalizado a una clase, como resultado, el compilador deja de crear el constructor predeterminado. , y si alguna vez se crea una instancia de la clase a través del constructor predeterminado, aparece este error. Simplemente agregue el constructor predeterminado explícitamente.
SF.

Respuestas:


170

El mensaje de error dice claramente que el constructor predeterminado se ha eliminado implícitamente . Incluso dice por qué: la clase contiene una variable constante, no estática, que no sería inicializada por el ctor predeterminado.

class X {
    const int x;
};

Como X::xes const, debe inicializarse, pero un ctor predeterminado normalmente no lo inicializaría (porque es un tipo POD). Por lo tanto, para obtener un ctor predeterminado, debe definir uno usted mismo (y debe inicializarse x). Puede tener el mismo tipo de situación con un miembro que es una referencia:

class X { 
    whatever &x;
};

Probablemente valga la pena señalar que ambos también deshabilitarán la creación implícita de un operador de asignación, esencialmente por la misma razón. El operador de asignación implícita normalmente realiza asignaciones por miembros, pero con un miembro constante o un miembro de referencia, no puede hacerlo porque el miembro no se puede asignar. Para que la asignación funcione, debe escribir su propio operador de asignación.

Esta es la razón por la que un constmiembro normalmente debe ser estático: cuando haces una asignación, no puedes asignar el miembro constante de todos modos. En un caso típico, todas sus instancias tendrán el mismo valor, por lo que también podrían compartir el acceso a una sola variable en lugar de tener muchas copias de una variable que tendrán el mismo valor.

Sin embargo, es posible, por supuesto, crear instancias con valores diferentes: usted (por ejemplo) pasa un valor cuando crea el objeto, por lo que dos objetos diferentes pueden tener dos valores diferentes. Sin embargo, si intenta hacer algo como intercambiarlos, el miembro const conservará su valor original en lugar de intercambiarse.


@Jeffry Coffin: el mensaje de error real se publicó como una edición, el mensaje de error inicial publicado fue soloC++ error: use of deleted function
Alok Save

1
@Als: Lo siento, probablemente debería haber sido explícito en el sentido de que no tenía la intención de insultarlo ni nada en ese orden, solo que lo que estaba disponible en ese momento hizo evidente que esas respuestas no eran correctas.
Jerry Coffin

No hay problema, no quise ser inflexible ... Tu respuesta es fantástica y explica mejor la situación. +1 de mí :)
Alok Save

Supongo que podría ayudarme con mi problema aquí, por favor: stackoverflow.com/questions/23349524/…
Saher Ahwal

2
@OllieFord: Eso depende. ¿Qué debería suceder si (por ejemplo) asigna un objeto con un valor en ese campo a otro que tiene un valor diferente en ese campo? Si debe sobrescribirse, entonces no puede ser constante. Si eso no debería permitirse en absoluto, entonces el valor podría ser realmente parte del tipo (por ejemplo, un parámetro de plantilla, si se conoce en el momento de la compilación).
Jerry Coffin

11

Está utilizando una función, que está marcada como deleted.
P.ej:

int doSomething( int ) = delete;

= Delete es una nueva característica de C ++ 0x. Significa que el compilador debe dejar de compilar inmediatamente y quejarse de que "esta función se elimina" una vez que el usuario usa dicha función.

Si ve este error, debe verificar la declaración de la función =delete.

Para saber más sobre esta nueva característica introducida en C ++ 0x, consulte esto .


7
Por curiosidad, ¿cuándo sería útil hacer algo así?
Pepe

@Peter: para evitar conversiones implícitas.
R. Martinho Fernandes

7
En realidad, dice "eliminado implícitamente porque ..." , el ejemplo anterior sería explícito.
Georg Fritzsche

@Peter R: parece que este es un ejemplo: en.wikipedia.org/wiki/…
shuttle87

1
@Downvoter: El mensaje de error real se publicó como una edición, el mensaje de error inicial publicado fue soloC++ error: use of deleted function
Alok Save

4

gcc 4.6 admite una nueva característica de funciones eliminadas, donde puede escribir

hdealt() = delete;

para deshabilitar el constructor predeterminado.

Aquí el compilador obviamente ha visto que no se puede generar un constructor predeterminado, y =deletelo hizo por usted.


2

Encontré este error al heredar de una clase abstracta y no implementar todos los métodos virtuales puros en mi subclase.


1
De manera similar, obtuve lo mismo al derivar public virtualde una clase base de segundo nivel donde la clase base de primer nivel tenía un constructor predeterminado eliminado explícitamente. La eliminación virtualsolucionó el problema sin tener que implementar todos los métodos.
Maitre Bart

1

En el estándar C ++ 0x actual, puede deshabilitar explícitamente los constructores predeterminados con la sintaxis de eliminación, por ejemplo

MyClass() = delete;

Gcc 4.6 es la primera versión que admite esta sintaxis, así que quizás ese sea el problema ...


Gcc 4.6 is the first version to support this syntaxSupongo que eso explicaría por qué nunca lo había visto antes, ya que recién comencé a usar gcc4.6.
traslado 87

2
He estado usando esta sintaxis con GCC 4.5 durante años. Me refiero a días.
R. Martinho Fernandes

Ah, debo haber estado pensando en ctors delegados que están en GCC 4.6.
jarmond

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.