Semântica em C ++ de `const const` vs` const`

149

No C ++ especificamente, quais são as diferenças semânticas entre, por exemplo:

static const int x = 0 ;

e

const int x = 0 ;

para ambos, staticcomo um enlace e um especificador de classe de armazenamento (ou seja, dentro e fora de uma função).

Clifford
fonte
7
staticé provavelmente a palavra-chave mais sobrecarregada em C ++. O significado do seu código varia amplamente, dependendo se está no escopo do espaço para nome, no escopo da classe ou no escopo da função. Você pode esclarecer isso.
SBI
1
@bi: Eu pensei que já tinha. Escopo da função (onde é um especificador de classe de armazenamento) e escopo do arquivo (onde é um especificador de ligação). Os membros da classe e as variáveis ​​com escopo de namespace especificamente não me interessam em relação a essa pergunta, embora se alguém achar que há uma distinção interessante, sinta-se à vontade para cobri-la também.
Clifford
@Clifford: Me desculpe, eu esqueci as últimas palavras. No entanto, isso revelou um mal-entendido de sua parte: no C ++, o escopo do arquivo é o escopo do espaço para nome. Se você declarar algo fora do espaço de nomes, ele simplesmente pertencerá ao espaço de nomes global (e poderá ser acessado por um prefixo ::sem identificador na frente). Não estou ciente de diferenças significativas entre o espaço para nome global e qualquer espaço para nome aninhado nele. Certamente não há staticobjetos a respeito .
sbi 14/09/10
1
O vínculo é diferente da visibilidade . Ao usá-los de forma intercambiável, você confundirá as pessoas com quem você conversa e provavelmente você também.
Ben Voigt
1
@ Ben, @ sbi: Eu não pretendia sugerir que o escopo do arquivo e a ligação estática fossem os mesmos, apenas que a ligação estática implica o escopo do arquivo. Nesse sentido, o escopo (ou visibilidade) é um atributo de ligação estática e externa, e também não é sinônimo. Eu sinto que a pergunta original permanece clara e bem formada, e que estamos apenas discutindo os comentários feitos em resposta à observação um tanto condescendente do sbi. Estamos discutindo semânticas imprecisas do inglês aqui, e não meu entendimento, então acho que podemos parar.
Clifford

Respostas:

128

No escopo do arquivo, não há diferença em C ++. consttorna o vínculo interno o padrão e todas as variáveis ​​globais têm vida útil estática. Mas a primeira variante tem o mesmo comportamento em C, portanto, esse pode ser um bom motivo para usá-lo.

Dentro de uma função, a segunda versão pode ser calculada a partir de parâmetros. Em C ou C ++, não precisa ser uma constante em tempo de compilação, como algumas outras linguagens exigem.

Dentro de uma classe, basicamente a mesma coisa que para funções. Um constvalor de instância pode ser calculado na lista de inicializadores do ctor . A static consté definido durante a inicialização e permanece inalterado pelo restante do programa. (Nota: o código para staticmembros parece um pouco diferente porque a declaração e a inicialização são separadas.)

Lembre-se, em C ++, constsignifica somente leitura , não constante . Se você tem um ponteiro para const, outras partes do programa podem alterar o valor enquanto você não está procurando. Se a variável foi definida com const, ninguém poderá alterá-la após a inicialização, mas a inicialização ainda pode ser arbitrariamente complexa.

Ben Voigt
fonte
1
Existe algo chamado escopo de arquivo? Eu estava apenas verificando $ 3,3 e acho que o mais próximo é o 'escopo do espaço para nome'. Meu entendimento está correto? O padrão C ++ 03 menciona o escopo do arquivo somente nos Apêndices
Chubsdad
2
Eu sugeriria que o escopo do arquivo é um artefato do vinculador e não do compilador, portanto, pode não receber muita atenção no padrão da linguagem. Estritamente, é provavelmente "escopo da unidade de compilação".
Clifford
8
+1 para a frase "const significa somente leitura, não constante", ou seja, "Compilador, se você vir alguém tentando modificar essa coisa const, latir muito alto". Esta é a razão pela qual algo pode ser constante e volátil ao mesmo tempo.
Dan
5
É mais "Compilador, se você me vê tentando modificar essa coisa const (ou dá permissão a alguém para fazê-lo)", late muito alto. Na maior parte do contexto, constaplica-se a uma visão da variável e não à própria variável, alguém pode ter uma não constvisão da mesma variável, e o compilador ficará bastante silencioso quando a modificar.
Ben Voigt
1
@ Ben: Só para esclarecer, C ++ 0x não remove esse uso específico de const, mas o novo constexprpode ser usado em vez (e em outros cenários também). Na verdade, o padrão C ++ 0x expande a capacidade de usar constnesse cenário para "tipos literais" não integrais. Eu acho que prefiro usar constexprnesses casos, já que você estaria quebrando a compatibilidade com os compiladores pré-C ++ 0x.
Michael Burr
4

O rascunho padrão do C ++ 17 constimplica staticno escopo do arquivo

Esta é a cotação do que foi mencionado em: https://stackoverflow.com/a/3709257/895245

C ++ 17 n4659 rascunho padrão 6.5 "Programa e ligação":

3 Um nome com escopo de espaço para nome (6.3.6) possui ligação interna se for o nome de

  • (3.1) - uma variável, função ou gabarito de função declarada explicitamente estática; ou,
  • (3.2) - uma variável não em linha do tipo qualificada const não volátil que não é declarada explicitamente externa nem anteriormente declarada com vínculo externo; ou
  • (3.3) - um membro de dados de uma união anônima.

Anexo C (informativo) Compatibilidade, C.1.2 Cláusula 6: "conceitos básicos" fornece a justificativa por que isso foi alterado de C:

6.5 [também 10.1.7]

Alteração: um nome do escopo do arquivo declarado explicitamente const, e não explicitamente declarado externo, possui vínculo interno, enquanto em C ele teria vínculo externo.

Justificativa: Como os objetos const podem ser usados ​​como valores durante a conversão em C ++, esse recurso solicita que os programadores forneçam um inicializador explícito para cada objeto const. Esse recurso permite que o usuário coloque objetos const nos arquivos de origem incluídos em mais de uma unidade de tradução.

Efeito no recurso original: mude para a semântica do recurso bem definido.

Dificuldade de conversão: transformação semântica.

Como amplamente utilizado: raramente.

Veja também: Por que const implica ligação interna em C ++, quando não em C?

O que você provavelmente quer fazer nos cabeçalhos

Explicado em detalhes em: O que significa 'const static' em C e C ++?

  • pré C ++ 17: extern no cabeçalho, definição no arquivo cpp
  • post C ++ 17: variável embutida no cabeçalho
Ciro Santilli adicionou uma nova foto
fonte
Obrigado, embora eu não ache que seja uma chance no C ++ 17 comparado com o C ++ 98, e a pergunta foi feita em 2010. Além disso, sua resposta lida apenas com a estática como um especificador de ligação (no escopo do espaço para nome) , e a pergunta feita especificamente sobre a semântica em diferentes contextos.
Clifford
@ Clifford sim, definitivamente mais antigo que o C ++ 17, com preguiça de ler todos os padrões ;-) Esclarecerá parte do escopo do arquivo.
Ciro Santilli respondeu