Em C / C ++, devo usar 'const' em parâmetros e variáveis ​​locais quando possível?

13

Esta pergunta é inspirada em uma pergunta sobre finalem java .

Em C / C ++, devo usar constsempre que possível?

Eu sei que já existe uma pergunta relacionada sobre o uso constde parâmetros . Infelizmente, essa pergunta e suas respostas não respondem totalmente à minha pergunta, porque é apenas sobre parâmetros de função, mas eu também gostaria de saber sobre outros casos (por exemplo: variáveis ​​locais).

Além disso, quase todas as respostas a essa pergunta dizem que devemos usar, constpois contém informações úteis sobre a acessibilidade das variáveis. Mas isso parece entrar em conflito com uma resposta sobre o uso final em Java, que afirma finalser supérfluo se não contiver informações adicionais e, portanto, deve ser omitido para manter o código curto e limpo.

Então, devo usar constsempre que possível? Se sim, por que o conselho constem C ++ é diferente do conselho finalem Java?

ocomfd
fonte

Respostas:

18

Primeiro de tudo, desde que você fez referência ao Java final, isso é um animal totalmente diferente do que const. Final significa que a referência não pode mudar, mas não diz nada sobre mutabilidade. Const vai além dizendo "uma referência const não pode sofrer mutação", o que é uma garantia muito mais forte. Para fazer isso em Java, o estado interno deve ser final e determinado no momento da construção. Const é muito mais fácil de usar, e um objeto existente pode ser "promovido" em uma referência const.

Sim, você deve usar const sempre que possível. Faz um contrato que seu código não vai mudar nada. Lembre-se, uma variável não-const pode ser passada para uma função que aceita um parâmetro const. Você sempre pode adicionar const, mas não tirá-lo (não sem um elenco const que é uma péssima idéia).

Às vezes, a correção de Const pode ser entediante, mas ajuda a garantir a imutabilidade. Isso é crucial no código multithread em que os threads compartilham objetos. Isso torna certas tarefas mais eficientes: em vez de copiar o estado, apenas reutilize o mesmo objeto imutável. As bibliotecas podem aceitar parâmetros const para garantir ao programador que não, seu objeto não será alterado de maneira imprevisível no buraco negro que é a coragem da biblioteca.


fonte
1
Voto positivo porque você explica isso finale constnão tem as mesmas garantias.
Bill Porta
2
A consistência é sobre gravabilidade, não sobre mutabilidade.
Basilevs 5/10
@Basilevs o que acontece se você escrever em um objeto? Isso muda. Como você muda um objeto? Escreva para ele.
4
O que acontece se você escrever em uma referência const? Um erro de tempo de compilação. O que acontece se você escrever no objeto que é referenciado em algum lugar pela referência const por meio de outra referência não-const? Isso muda. Objetos imutáveis ​​não podem sofrer mutações; portanto, a referência constante não faz necessariamente referência a objetos imutáveis.
Basilevs 5/10
@Basilevs sua observação se aplica apenas a const refs. Se um objeto em si é declarado const (não apenas a referência), é mais ou menos imutável (a menos que alguém nefastamente elimine a constância).
Matthew James Briggs
4

Pessoalmente, constlevo muito pouco tempo para escrever e muito pouco tempo para ler, geralmente muito menos do que o necessário para verificar se algum código altera a variável e isso realmente me impede de escrever bugs (alguém já incrementou acidentalmente seu iterador final? Etc)

Também acho que ser rigoroso quanto ao uso de const me orienta para um código melhor de outras maneiras, como a criação de funções auxiliares para executar uma inicialização não trivial.

Bwmat
fonte
4

Discordo dos outros pôsteres e recomendo que você não use de nível superior constem variáveis ​​e parâmetros locais. (Referências e indicadores para const, ou seja const T&, são diferentes, e você deve usá-los para correção sempre que for apropriado.)

As vantagens do nível superior constsão:

  • Torna claro que as variáveis ​​locais não devem ser mutadas.
  • Dá um erro do compilador se você acidentalmente tentar modificá-los.

As desvantagens são:

  • Desordem visual.
  • Não pode ser usado em variáveis ​​"pseudo-const", ou seja, variáveis ​​que são inicializadas de alguma maneira mais complicadas que a construção direta, mas não modificadas depois, por exemplo, usando getline:

    std::string line; // cannot be const
    std::getline(std::cin, line);
    // line should be const from here on out
  • Impede a otimização da mudança de chamada e retorno de função:

    std::string f1();
    std::string f2(std::string s);
    std::string f3() {
      const std::string s = f1(); // s is not meant to be modified
      // but I still want the move optimization here:
      const std::string result = f2(std::move(s)); // this doesn't move
      // and I want the compiler to move out here:
      return result; // this will probably RVO, but if not, the move
                     // constructor will not be used due to the const
    }

Eu trabalhei em uma base de código onde o local constera muito usado, e não achei nada útil, mas ele preenchia o código com pessimizações sutis, como acima. Pessoalmente, prefiro adotar uma política geral de modificar variáveis ​​o mais raramente possível e tornar as funções pequenas o suficiente para que o uso de uma variável seja óbvio, e mesmo que seja modificado, a complexidade da função é baixa o suficiente para torná-la não -questão.

Sebastian Redl
fonte
2
Seu ponto sobre movimento-de está mostrando onde você não está usando o local de forma const, como você (pretende) modificá-lo com o movimento
Caleth
1
@ Caleth Não, esse é o ponto. Não pretendo modificá-lo. Eu só quero passar o valor, ou devolvê-lo, e quero que seja eficiente. Conceitualmente, a modificação é apenas uma otimização, que não deve ser observável (já que as variáveis ​​não são usadas posteriormente). Na prática, sim, há uma modificação, pois o C ++ não possui movimentos destrutivos verdadeiros (como o Rust). É exatamente por isso que não quero constlocais: porque impede modificações técnicas, não apenas modificações conceituais.
Sebastian Redl 25/10
2
Você não deseja modificar o valor , mas deseja modificar a variável . Em vez disso você pode usar const & vez, e modificar nem
Caleth
2

A constpalavra-chave deve ser usada para variáveis ​​locais, assim como parâmetros. É útil porque:

  • Mais fácil de ler o código. Quando alguém lê a declaração da variável, ela sabe que não vai mudar. Menos uma coisa a se preocupar ao ler seu código.
  • Impedir que você acidentalmente modifique a variável
  • Sem penalidade de execução, tudo é verificado estaticamente. É como um almoço grátis, constdeve levar apenas um segundo para escrever, então não é grande coisa.
  • É sempre uma boa ideia criar suas variáveis ​​/ parâmetros em seus aplicativos multithread. Mesmo seu aplicativo não é multiencadeado, ainda é um bom hábito.
  • Você oferece uma oportunidade para o seu compilador C ++ otimizar seu código.

Observe que não há resposta certa / errada aqui. No seu link, a pessoa que respondeu com mais votos positivos finalnão deve ser usada localmente. No entanto, o próximo respondente o recomendou fortemente.

Se sua função é simples e trivial , você não deve adicionar constporque todos entendem sua intenção. No entanto, se a lógica em sua função não for trivial, você deve usar a palavra-chave Lembre-se, há pouco a perder.

Olá Mundo
fonte