define - why use const in c++




Parola chiave const C++: usare liberamente? (8)

Avere un tipo primitivo passato per valore const è praticamente inutile. Passare un const a una funzione è generalmente utile come un contratto con il chiamante che la funzione non modificherà il valore. In questo caso, poiché l'int è passato per valore, la funzione non può apportare modifiche che saranno visibili al di fuori della funzione.

D'altra parte, le rreferenze e i tipi di oggetti non banali dovrebbero sempre usare const se non ci saranno modifiche apportate all'oggetto. In teoria questo potrebbe consentire qualche ottimizzazione, ma la grande vittoria è il contratto che ho menzionato sopra. Il rovescio della medaglia è, naturalmente, che può rendere la tua interfaccia molto più grande, e constarlo come una cosa difficile da riadattare in un sistema esistente (o con un'API di terze parti che non usa const ovunque).

https://code.i-harness.com

Nelle seguenti funzioni C ++:

void MyFunction(int age, House &purchased_house)
{
    ...
}


void MyFunction(const int age, House &purchased_house)
{
    ...
}

Che è migliore?

In entrambi, "l'età" è passata in base al valore. Mi chiedo se la parola chiave 'const' sia necessaria: mi sembra ridondante, ma anche utile (come indicazione aggiuntiva che la variabile non cambierà).

Qualcuno ha qualche opinione su quale (se esiste) di quanto sopra sono migliori?


Bene, come altri hanno già detto, dal punto di vista del linguaggio C ++, il precedente const non ha alcun effetto sulla firma della funzione, cioè il tipo di funzione rimane lo stesso indipendentemente dal fatto che il const sia presente o meno. L'unico effetto che ha al livello del linguaggio C ++ astratto è che non è possibile modificare questo parametro all'interno del corpo della funzione.

Tuttavia, al livello più basso, il modificatore const applicato al valore del parametro può avere alcuni vantaggi di ottimizzazione, dato un compilatore sufficientemente intelligente. Prendi in considerazione due funzioni con lo stesso set di parametri (per semplicità)

int foo(const int a, const double b, const long c) {
   /* whatever */
}

void bar(const int a, const double b, const long c) {
   /* whatever */
}

Diciamo da qualche parte nel codice che sono chiamati come segue

foo(x, d, m);
bar(x, d, m);

Normalmente, i compilatori preparano lo stack frame con argomenti prima che chiamino una funzione. In questo caso lo stack verrà preparato due volte: una volta per ogni chiamata. Ma un compilatore intelligente potrebbe rendersi conto che dal momento che queste funzioni non cambiano i loro valori dei parametri locali (dichiarati con const ), l'argomento impostato per la prima chiamata può essere tranquillamente riutilizzato per la seconda chiamata. Quindi può preparare lo stack una sola volta.

Questa è un'ottimizzazione piuttosto rara e oscura, che può funzionare solo quando la definizione della funzione è nota al momento della chiamata (o la stessa unità di traduzione o un compilatore avanzato di ottimizzazione globale), ma a volte potrebbe valere la pena di essere menzionata.

Non è corretto dire che è "senza valore" o "non ha alcun effetto", anche se con un compilatore tipico potrebbe essere il caso.

Un'altra considerazione che vale la pena menzionare è di natura diversa. Esistono standard di codifica, che richiedono ai programmatori di non modificare i valori dei parametri iniziali, poiché in "non utilizzare i parametri come variabili locali ordinarie, i valori dei parametri dovrebbero rimanere invariati per tutta la funzione". Questo tipo ha senso, poiché a volte rende più facile determinare quali valori dei parametri la funzione è stata originariamente fornita (mentre nel debugger, all'interno del corpo della funzione). Per aiutare a far rispettare questo standard di codifica, le persone potrebbero usare gli const sui valori dei parametri. Se ne valga la pena o no è una domanda diversa ...


Ecco alcuni ottimi articoli e un libro che ho trovato che spiega i vantaggi dell'utilizzo di const:

Posso proporvi la seguente massima?

Se un oggetto / variabile può essere qualificato è costante, dovrebbe essere. Nel peggiore dei casi, non costerà nulla. Nella migliore delle ipotesi, documenterai il ruolo dell'oggetto / variabile nel tuo codice e permetterà al compilatore di ottimizzare ulteriormente il tuo codice.

Alcuni compilatori trascurano di sfruttare il potenziale dell'ottimizzazione con l'uso di "const" e ciò ha portato molti esperti a trascurare l'uso di parametri costanti in base al valore quando potrebbe essere utilizzato. Questa pratica richiede più rigore, ma non sarà dannosa. Nel peggiore dei casi, non perdi nulla, ma non guadagni nulla e nel migliore dei casi, vinci usando questo approccio.

Per coloro che non sembrano comprendere l'utilità di un const in un parametro di valore di una funzione / metodo ... ecco un breve esempio che spiega perché:

cpp

void WriteSequence(int const *, const int);

int main()
{
    int Array[] = { 2, 3, 4, 10, 12 };
    WriteSequence(Array, 5);
}


#include <iostream>
using std::cout;
using std::endl;
void WriteSequence(int const *Array, const int MAX)
{
    for (int const * i = Array; i != Array + MAX; ++i)
      cout << *i << endl;
}

Cosa sarebbe accaduto se avessi rimosso il const di fronte a MAX MAX e io avessi scritto MAX + 1 dentro così?

void WriteSequence(int Array[], int MAX)
{
    MAX += MAX;
    for (int * i = Array; i != Array + MAX; ++i)
      cout << *i << endl;
}

Bene, il tuo programma andrebbe in crash! Ora, perché qualcuno dovrebbe scrivere "MAX + = MAX;" ? Forse errore umano, forse il programmatore non si sentiva bene quel giorno o forse il programmatore semplicemente non sapeva come scrivere codice C / C ++. Se aveste avuto const, il codice non sarebbe nemmeno stato compilato!

Il codice di sicurezza è un buon codice e non costa nulla aggiungere "const" quando ce l'hai!

Ecco una risposta da un post diverso per una domanda molto simile:

"const è inutile quando l'argomento viene passato per valore poiché non si modificherà l'oggetto del chiamante."

Sbagliato.

Si tratta di auto-documentare il tuo codice e le tue ipotesi.

Se il tuo codice ha molte persone che lavorano su di esso e le tue funzioni non sono banali, dovresti contrassegnare "const" tutto ciò che puoi. Quando scrivi un codice di forza industriale, dovresti sempre presumere che i tuoi colleghi siano psicopatici che cercano di ottenere in qualsiasi modo (soprattutto perché spesso è te stesso in futuro).

Inoltre, come qualcuno ha menzionato prima, potrebbe aiutare il compilatore a ottimizzare le cose un po '(anche se è un campo lungo).

Ecco il link: answer .


Hai ragione, l'unico scopo di "const int age" è che l'età non può essere cambiata. Questo può essere tuttavia molto confuso per la maggior parte dei programmatori. Quindi se questo approccio non è ampiamente utilizzato nel tuo codice, consiglierei di omettere const.


La seconda variante è migliore. Nel primo si può cambiare accidentalmente l'età variabile.


Non solo indichi che non cambierà, impedirà al tuo codice di pensarlo e verrà catturato al momento della compilazione.


Raccomando di leggere Herb Sutter. C ++ eccezionale . C'è un capitolo "Const-Correctness".

"In effetti, per il compilatore, la firma della funzione è la stessa sia che si includa questo const davanti a un parametro di valore o meno."

Significa che questa firma

void print(int number);

è effettivamente lo stesso di questo:

void print(int const number);

Quindi, per il compilatore non c'è differenza su come si dichiara una funzione. E non puoi sovraccaricarlo mettendo la parola chiave const davanti a un parametro pass by value.

Leggi oltre, ciò che Herb Sutter consiglia:

Msgstr "Evita i parametri const-pass-by-value nelle dichiarazioni di funzioni, ma continua a fare il parametro const nella stessa definizione della funzione se non verrà modificato."

Raccomanda di evitare questo:

void print(int const number);

Perché quel const è confusionario, prolisso e ridondante.

Ma nella definizione, dovresti farlo (se non cambierai il parametro):

void print(int const number)
{
   // I don't want to change the number accidentally here
   ...
}

Quindi, sarai sicuro che anche dopo 1000 linee di corpo della funzione hai sempre il numero non toccato. Il compilatore ti proibirà di passare il numero come riferimento non const a un'altra funzione.


Un vantaggio dell'uso di const è che non è possibile modificare accidentalmente il valore age nel mezzo di MyFunction (nel caso in cui si dimentichi che non è stato passato per riferimento). Uno "svantaggio" è che non è possibile riciclare l' age con codice come foo.process(++age); .





const