Pergunta

Eu sei que há alguns pergunta sobre correção const onde se afirma que a declaração de uma função e sua definição não precisam concordar para parâmetros de valor. Isso ocorre porque o constness de um parâmetro de valor só importa dentro da função. Isso é bom:

// header
int func(int i);

// cpp
int func(const int i) {
    return i;
}

Está fazendo isso realmente uma boa prática? Porque eu nunca vi ninguém fazê-lo. Eu vi essa citação (não tenho certeza da fonte) em outros lugares este foi discutido:

"Na verdade, para o compilador, a assinatura da função é o mesmo se você incluir esta const na frente de um parâmetro de valor ou não."

"Evite const passagem por valor parâmetros em declarações de função. Ainda assim fazer a const parâmetro na definição da mesma função, se não será modificado."

O segundo parágrafo diz para não colocar o const na declaração. Suponho que isso é porque o constness de um parâmetro valor é sem sentido como parte de uma definição de interface. É um detalhe de implementação.

Com base nesta recomendação, é também recomendado para os valores de ponteiro de parâmetros de ponteiro? (Não faz sentido em um parâmetro de referência desde que você não pode transferir uma referência.)

// header
int func1(int* i);
int func2(int* i);

// cpp
int func1(int* i) {
    int x = 0;

    *i = 3; // compiles without error
    i = &x; // compiles without error

    return *i;
}
int func2(int* const i) {
    int x = 0;

    *i = 3; // compiles without error
    i = &x; // compile error

    return *i;
}

Resumo: Fazer parâmetros de valor é útil para pegar alguns erros de lógica. É uma boa prática? Você ir ao extremo de deixar o const fora do arquivo de cabeçalho? É tão útil para valores de ponteiro const? Por que ou por que não?

Algumas referências:

C ++ const palavra-chave -? Uso liberalmente Uso de 'const' para parâmetros de função

Um exemplo de quando parâmetros de valores const são úteis:

bool are_ints_equal(const int i, const int j) {
    if (i = j) { // without the consts this would compile without error
        return true;
    } else {
        return false;
    }
    // return i = j; // I know it can be shortened
}
Foi útil?

Solução

A minha opinião sobre ele:

Não é uma má idéia, mas a questão é menor e sua energia pode ser melhor gasto em outras coisas.

Em sua pergunta você forneceu um bom exemplo de quando se pode pegar um erro, mas ocasionalmente você também acabam fazendo algo parecido com isto:

void foo(const int count ...)
{
   int temp = count;  // can't modify count, so we need a copy of it
   ++temp;

   /* ... */
}

Os prós e contras são menores de qualquer forma.

Outras dicas

Eu li muitas vezes que fazer parâmetros de valor em um const função é uma coisa ruim para fazer, porque isso é desnecessário.

No entanto, acho que é ocasionalmente útil para mim como um cheque que minha implementação não fazer algo que eu não pretendo (como no exemplo no final da sua pergunta).

Assim, enquanto ela não pode agregar valor para o chamador, ele às vezes adicionar um pouco de valor para mim como um implementador, e não tirar nada do chamador. Então eu vejo nenhum mal usá-lo.

Por exemplo, eu pode ser a implementação de uma função C que leva um par de ponteiros de um tampão - um apontador para o início, e um ponteiro para o fim. Vou colocar os dados no buffer, mas quero garantir que eu não saturar o fim. Então, dentro da função há código que irá incrementar um ponteiro como eu estou adicionando dados a ele. Fazendo o ponteiro para o final do buffer de um parâmetro const vai garantir que eu não codificam um bug que acidentalmente incrementa o ponteiro fronteira final em vez do ponteiro Eu realmente deveria ser incrementado.

Assim, uma função FillArray com uma assinatura como esta:

size_t fillArray( data_t* pStart, data_t* const pEnd);

vai me impedir de acidentalmente incrementando pEnd quando eu realmente quero pStart incremento. Não é uma grande coisa, mas eu tenho certeza que todo mundo que tem programado para qualquer período de tempo em C foi executado através de tal bug a.

Infelizmente, alguns compiladores (eu estou olhando para você, Sun CC!) Incorretamente diferenciar entre argumentos declarado const e os não declarados assim, e você pode obter erros sobre as funções indefinidas.

Eu acho que isso depende do seu estilo pessoal.

Ele não adicionar ou subtrair ao que os clientes podem passar para a sua função. Em essência é como uma afirmação de tempo de compilação. Se ele ajuda você a saber que o valor não vai mudar, vá em frente e fazê-lo, mas eu não vejo um grande motivo para os outros a fazê-lo.

Uma das razões que eu não poderia fazê-lo é que o const-ness do parâmetro valor é um detalhe de implementação que seus clientes não precisam saber. Se você mais tarde (propositadamente) mudar a sua função para que ele realmente faz alterar esse valor, você precisará alterar a assinatura de sua função, o que irá forçar seus clientes a re-compilação.

Isto é semelhante ao que algumas pessoas recomendam ter nenhum método virtuais públicos (as funções virtuais-ness é um detalhe de implementação que deve ser escondido dos clientes), mas eu não estou nesse campo particular.

Se houver const palavra-chave presente; isso significa que o valor de 'i' (que é do tipo const) não pode ser modificada. Se o valor de 'i' é alterado dentro do compilador função foo vai jogar de erro: "

Não é possível modificar objeto const

Mas mudar '* i' (ou seja, * i = 3;) significa que não estão mudando o valor de 'i' mas o valor de endereço apontado pelo 'i'

Na verdade, a função const é apropriado para grandes objetos que não devem ser alteradas por função.

Todos nós temos de desvendar alguém é código C ++ de vez em quando. E que alguém é código C ++ é uma bagunça completa, por definição:. D

Assim, a primeira coisa que eu sempre faço para decifrá-lo (fluxo de dados locais e globais) é colocado const em cada definição de variável até compilador reclama. Isto também significa argumentos de valor-qualificação const, e isso realmente ajuda a evitar variáveis ??que foram modificados no meio da função sem me perceber ...

Então, eu realmente aprecio quando esse alguém tem const em todos os lugares (incluindo parâmetros de valor): D

Eu gosto de correção const para situações como esta:
void foo(const Bar &b) //I know b cannot be changed
{
//do something with b
}

Isto deixa-me usar b sem medo de modificá-lo, mas eu não ter que pagar o custo de um construtor de cópia.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top