C ++: referência const, antes vs após especificador de tipo

145

Qual é a diferença entre os argumentos em:

int foo1(const Fred &arg) {
...
}

e

int foo2(Fred const &arg) {
...
}

? Não vejo este caso coberto nas perguntas frequentes sobre parashift.

eisbaw
fonte
2
isso é uma pergunta sobre estilo? "const Fred" soa bem em inglês, mas "Fred const" parece melhor para mim.
LatinSuD
1
Em uma nota relacionada, há alguma razão deve-se preferir Fred const &argmais Fred const& arg? Eu gosto mais deste último porque const&existe uma unidade que significa "constref", e o nome argé separado por um espaço em branco de todos os especificadores de tipo.
Frank
4
@dehmann: Mas int const& refnão significa 'const ref', mas 'ref to const'.
Cedric H.
1
Duplicado de: stackoverflow.com/questions/2640446/…
Michael Aaron Safyan

Respostas:

112

Nenhuma diferença, como const, é lida da direita para a esquerda em relação ao &, portanto, ambos representam uma referência a uma instância imutável do Fred.

Fred& constsignificaria que a própria referência é imutável, o que é redundante ; ao lidar com ponteiros const ambos Fred const*e Fred* constsão válidos, mas diferentes.

É uma questão de estilo, mas eu prefiro usar constcomo sufixo, pois ele pode ser aplicado de forma consistente, incluindo funções de membro const .

Sean Fausett
fonte
Então, qual é o objetivo de std::is_const<const T&>::valueser false?
abyss.7
@ abyss.7 é uma referência a const T; a referência é mutável.
Sean Fausett 15/03/19
125

Comportamento

Não há diferença semântica entre const T&e T const&; o idioma os trata como o mesmo tipo. (O mesmo se aplica a const T*e T const*.)

Por uma questão de estilo

No entanto, em relação a qual você deve preferir estilisticamente, discordo de muitas das outras respostas e prefiro const T&(e const T*):

  • const T&é o estilo usado no livro da linguagem de programação C ++ da Stroustrup .
  • const T& é o estilo usado no próprio padrão C ++.
  • const T*é o estilo usado no livro The C Programming Language da K&R .
  • const T* é o estilo usado no padrão C.
  • Devido aos fatores acima, acho const T&/ const T*tenho muito mais inércia que T const&/ T const*. const T&/ const T*empiricamente parece muito mais comum para mim do que T const&/ T const*em todos os códigos C ++ e C que eu já vi. Eu acho que seguir práticas comuns é mais legível do que seguir dogmaticamente as regras de análise da direita para a esquerda.
  • Com T const*, parece mais fácil deslocar o *as T* const(especialmente se as pessoas não estão tão acostumadas a ele). Por outro lado, const* Tnão é sintaxe legal.

E a regra de análise da direita para a esquerda?

Com relação a todo o argumento de análise da direita para a esquerda que as pessoas parecem gostar de usar: como mencionei em um comentário para outra resposta, também const T&lê bem da direita para a esquerda. É uma referência a uma constante T. "T" e "constante" podem funcionar como adjetivo ou substantivo. (Além disso, a leitura da T const*direita para a esquerda pode ser ambígua, pois pode ser interpretada incorretamente como "constante de ponteiro para T" em vez de como "ponteiro para constante T".)

jamesdlin
fonte
3
+1, concordou. Ao ler o código, é mais fácil identificar uma const se a linha começa com const. A regra direita-esquerda é realmente necessária apenas ao analisar manualmente declarações de tipo especialmente peludas. Por que não otimizar para o caso mais comum? Além disso, IMHO, se você escrever declarações de tipo, precisará executar manualmente um FSM na sua cabeça, estará fazendo errado.
Andreas Magnusson
2
-1. Independentemente de quão justificadas sejam suas conclusões e de quanto eu pessoalmente concordo com elas, elas não estão respondendo diretamente à pergunta . Isso faz com que a segunda resposta a uma pergunta simples pareça uma tagarelice fora de tópico sobre algumas máquinas subaquáticas bagunçadas, sem conclusões, sem resposta direta - nada. Você receberá meu voto positivo quando adicionar um resumo simples e claro, afirmando " Não, não há diferença semântica entre as duas sintaxes , mas há algumas considerações estilísticas da seguinte forma ...". E só então todas essas balas.
ulidtko
1
Na IMO, o motivo const T&é melhor: 1- Lemos o código da esquerda para a direita. E 2- Ao descrever um novo conceito, partimos do conceito mais geral para o mais específico. Aqui, a constpalavra-chave é mais geral, pois divide o espaço variável em duas categorias, enquanto o especificador de tipo o divide em várias.
precisa saber é o seguinte
"ponteiro para" deve ficar junto. Portanto, não há ambiguidade paraT const*
Dexter
13

Embora sejam a mesma coisa, para manter a consistência com a regra RIGHT-LEFT sobre a análise de declarações C e C ++, é melhor escreverFred const &arg

Consulte também isso para desenvolver mais entendimento sobre declarações, qualificadores e declaradores.

Chubsdad
fonte
1
Eu prefiro o sufixo, porque funciona melhor com a typedefexpansão. Exemplo: typedef int* pointer;, const pointer não é const int* , é int* const. A forma do sufixo não é estranha.
Matthieu M.
4
A IMO também const T&lê bem da direita para a esquerda; é uma referência a uma constante T. Te constantcada um pode funcionar como um adjetivo ou um substantivo.
jamesdlin
7

Ambos funcionam, e aqui está a explicação do homem que o escreveu.
Para citá-lo:

Por quê? Quando inventei "const" (inicialmente chamado "readonly" e tinha um "writeonly" correspondente), permiti que ele fosse antes ou depois do tipo, porque era possível fazê-lo sem ambiguidade.

Padrão
fonte
3

Referências não funcionam da mesma maneira que ponteiros: para ponteiros, você pode ter 'const pointers' ( type * const p) e 'ponteiro para const' ( const type * pou type const * p).

Mas você não tem isso para referências: uma referência sempre se refere ao mesmo objeto; nesse sentido, você pode considerar que 'referências' são 'referências const' (da mesma maneira que você pode ter 'const ponteiros').

Portanto, algo como 'type & const ref' não é legal. Você pode ter apenas 'referência ao tipo' ( type &ref) e 'referência ao tipo constante' ( const type &refou type const &ref; ambos são exatamente equivalentes).

Uma última coisa: mesmo que const typepareça mais correta em inglês, a escrita type constpermite uma compreensão mais sistemática das declarações "da direita para a esquerda": int const & refpode ser lida se 'ref é uma referência a uma constante int'. Ou exemplo mais complicado:, int const * const & refref é uma referência a um ponteiro constante para uma constante int.

Conclusão: na sua pergunta, ambos são exatamente equivalentes.

Cedric H.
fonte