erro: uso de função excluída


121

Tenho trabalhado em alguns códigos C ++ que um amigo escreveu e recebo o seguinte erro que nunca vi antes ao compilar com 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

Edit: Isso vem de uma parte do código usando boost MSM: Boost Webpage

Edit2: Não é = delete()usado em nenhum lugar no código-fonte.

De modo geral, o que significa esse erro? O que devo procurar quando esse tipo de erro ocorrer?


4
e o código que você está compilando?
ColWhi

Eu estava mais apenas me perguntando o que significava o erro? Eu preciso postar o código para isso também?
translado 87 de

1
gcc.gnu.org/bugzilla/show_bug.cgi?id=47417 pode ajudar, você também está usando boost?
ColWhi

@Sasquiha, sim, estou usando boost MSM.
translado 87 de

20
Já que isso surge como a primeira correspondência do Google para esse tipo de erro - não é o caso aqui, mas a causa mais comum para esse tipo de erro é depois que você adicionou algum construtor personalizado a uma classe - como resultado, o compilador para de criar o construtor padrão , e se uma instância da classe for criada por meio do construtor padrão, este erro aparecerá. Basta adicionar o construtor padrão explicitamente.
SF.

Respostas:


170

A mensagem de erro diz claramente que o construtor padrão foi excluído implicitamente . Ele até diz o porquê: a classe contém uma variável const não estática, que não seria inicializada pelo ctor padrão.

class X {
    const int x;
};

Desde X::xé const, ele deve ser inicializado - mas um ctor padrão normalmente não inicializá-lo (porque é um tipo POD). Portanto, para obter um ctor padrão, você precisa definir um (e ele deve inicializar x). Você pode ter o mesmo tipo de situação com um membro que é uma referência:

class X { 
    whatever &x;
};

Provavelmente, vale a pena notar que ambos também desabilitarão a criação implícita de um operador de atribuição, essencialmente pelo mesmo motivo. O operador de atribuição implícita normalmente faz a atribuição de membros, mas com um membro const ou membro de referência, ele não pode fazer isso porque o membro não pode ser atribuído. Para fazer a atribuição funcionar, você precisa escrever seu próprio operador de atribuição.

É por isso que um constmembro normalmente deve ser estático - quando você faz uma atribuição, você não pode atribuir o membro const de qualquer maneira. Em um caso típico, todas as suas instâncias terão o mesmo valor, então elas também podem compartilhar o acesso a uma única variável em vez de ter muitas cópias de uma variável que terá o mesmo valor.

É possível, claro, criar instâncias com valores diferentes - você (por exemplo) passa um valor ao criar o objeto, então dois objetos diferentes podem ter dois valores diferentes. Se, entretanto, você tentar fazer algo como trocá-los, o membro const manterá seu valor original em vez de ser trocado.


@Jeffry Coffin: A mensagem de erro real foi postada como uma edição, a mensagem de erro inicial postada foi apenasC++ error: use of deleted function
Alok Save

1
@Als: Desculpe, provavelmente eu deveria ter sido explícito que não pretendia isso como um insulto ou qualquer coisa dessa ordem, apenas que o que estava disponível no momento tornava aparente que essas respostas não estavam certas.
Jerry Coffin

Sem problemas, eu não queria ser inflexível ... Sua resposta é fantástica e explica melhor a situação. +1 de mim :)
Alok Save

Suponho que você possa me ajudar com meu problema aqui, por favor: stackoverflow.com/questions/23349524/…
Saher Ahwal

2
@OllieFord: Depende. O que deve acontecer se (por exemplo) você atribuir um objeto com um valor nesse campo a outro que tem um valor diferente nesse campo? Se for substituído, não pode ser constante. Se isso não deveria ser permitido, então o valor pode realmente ser parte do tipo (por exemplo, um parâmetro de modelo, se conhecido em tempo de compilação).
Jerry Coffin

11

Você está usando uma função marcada como deleted.
Por exemplo:

int doSomething( int ) = delete;

O = delete é um novo recurso do C ++ 0x. Isso significa que o compilador deve parar imediatamente de compilar e reclamar "esta função foi excluída" assim que o usuário usar essa função.

Se você vir esse erro, deve verificar a declaração da função para =delete.

Para saber mais sobre este novo recurso introduzido em C ++ 0x, verifique isto .


7
Por curiosidade, quando fazer algo assim seria útil?
Pepe de

@Peter: para evitar conversões implícitas.
R. Martinho Fernandes

7
Na verdade, diz "excluído implicitamente porque ..." , o exemplo acima seria explícito.
Georg Fritzsche

@Peter R: parece que este é um exemplo: en.wikipedia.org/wiki/…
shuttle87

1
@Downvoter: A mensagem de erro real foi postada como uma edição, a mensagem de erro inicial postada era apenasC++ error: use of deleted function
Alok Save

4

gcc 4.6 suporta um novo recurso de funções excluídas, onde você pode escrever

hdealt() = delete;

para desativar o construtor padrão.

Aqui, o compilador obviamente viu que um construtor padrão não pode ser gerado e =deleteo fez para você.


2

Encontrei esse erro ao herdar de uma classe abstrata e não implementar todos os métodos virtuais puros em minha subclasse.


1
Da mesma forma, obtive o mesmo derivando public virtualde uma classe base de 2º nível, onde a classe base de 1º nível tinha um construtor padrão explicitamente excluído. A remoção virtualcorrigiu o problema sem a necessidade de implementar todos os métodos.
Maitre Bart

1

No padrão C ++ 0x atual, você pode desabilitar explicitamente os construtores padrão com a sintaxe de exclusão, por exemplo

MyClass() = delete;

Gcc 4.6 é a primeira versão a suportar esta sintaxe, então talvez seja esse o problema ...


Gcc 4.6 is the first version to support this syntaxAcho que isso explicaria por que nunca o vi antes, pois comecei a usar o gcc4.6 recentemente.
translado 87 de

2
Tenho usado essa sintaxe com o GCC 4.5 há anos. Quero dizer dias.
R. Martinho Fernandes

Ah, devo ter pensado em ctors delegados que estão no GCC 4.6.
jarmond de

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.