c++ Uso di 'const' per i parametri di funzione





15 Answers

"const è inutile quando l'argomento viene passato per valore poiché non si modifica 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 detto prima, potrebbe aiutare il compilatore a ottimizzare un po 'le cose (anche se è un campo lungo).

c++ const

Quanto vai lontano con const ? Realizzi semplicemente le funzioni quando necessario o vai tutto il maiale e lo usi ovunque? Ad esempio, immagina un semplice mutatore che prende un singolo parametro booleano:

void SetValue(const bool b) { my_val_ = b; }

Questo const davvero utile? Personalmente scelgo di usarlo ampiamente, compresi i parametri, ma in questo caso mi chiedo se ne valga la pena?

Sono stato anche sorpreso di apprendere che puoi omettere const dai parametri in una dichiarazione di funzione, ma puoi includerlo nella definizione della funzione, ad esempio:

.h file

void func(int n, long l);

file .cpp

void func(const int n, const long l)

C'è una ragione per questo? Sembra un po 'insolito per me.




Le seguenti due righe sono funzionalmente equivalenti:

int foo (int a);
int foo (const int a);

Ovviamente non sarai in grado di modificare a nel corpo di foo se è definito il secondo modo, ma non c'è differenza dall'esterno.

Dove const davvero utile è con parametri di riferimento o puntatore:

int foo (const BigStruct &a);
int foo (const BigStruct *a);

Quello che dice è che foo può prendere un grande parametro, forse una struttura dati di dimensioni gigabyte, senza copiarlo. Inoltre, dice al chiamante, "Foo non * cambierà il contenuto di quel parametro." Anche il passaggio a un riferimento const consente al compilatore di prendere determinate decisioni sulle prestazioni.

*: A meno che non elimini la costanza, ma questo è un altro post.




const dovrebbe essere il default in C ++. Come questo :

int i = 5 ; // i is a constant

var int i = 5 ; // i is a real variable



C'è una buona discussione su questo argomento nei vecchi articoli "Guru della settimana" su comp.lang.c ++, here moderati.

L'articolo GOTW corrispondente è disponibile sul sito Web di Herb Sutter here .




Uso i parametri const su function che sono riferimenti (o puntatori) che sono solo [in] dati e non saranno modificati dalla funzione. Significato, quando lo scopo dell'utilizzo di un riferimento è evitare di copiare i dati e non consentire di modificare il parametro passato.

L'inserimento di const nel parametro b booleano nell'esempio mette solo un vincolo sull'implementazione e non contribuisce all'interfaccia della classe (sebbene di solito non sia consigliabile modificare i parametri).

La firma della funzione per

void foo(int a);

e

void foo(const int a);

è lo stesso, il che spiega il tuo .c e .h

Asaf




Ah, un duro. Da un lato, una dichiarazione è un contratto e in realtà non ha senso passare un argomento const per valore. D'altra parte, se si guarda all'implementazione della funzione, si dà al compilatore più possibilità di ottimizzare se si dichiara una costante di argomento.




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

const deve essere preferito quando si passa per riferimento, a meno che lo scopo della funzione sia quello di modificare il valore passato.

Infine, una funzione che non modifica l'oggetto corrente (questo) può, e probabilmente dovrebbe essere dichiarata const. Un esempio è qui sotto:

int SomeClass::GetValue() const {return m_internalValue;}

Questa è una promessa per non modificare l'oggetto a cui viene applicata questa chiamata. In altre parole, puoi chiamare:

const SomeClass* pSomeClass;
pSomeClass->GetValue();

Se la funzione non fosse const, ciò comporterebbe un avvertimento del compilatore.




Nel caso in cui menzioni, non ha alcun effetto sui chiamanti della tua API, motivo per cui non è comunemente fatto (e non è necessario nell'intestazione). Influisce solo sull'implementazione della tua funzione.

Non è una cosa particolarmente brutta da fare, ma i vantaggi non sono grandi perché non influisce sulla tua API, e aggiunge la digitazione, quindi di solito non è fatta.




Tendo a usare const ovunque possibile. (O altra parola chiave appropriata per la lingua di destinazione.) Lo faccio puramente perché consente al compilatore di fare ulteriori ottimizzazioni che non sarebbe in grado di fare altrimenti. Dal momento che non ho idea di cosa possano essere queste ottimizzazioni, lo faccio sempre, anche dove sembra sciocco.

Per quanto ne so, il compilatore potrebbe benissimo vedere un parametro const value, e dire, "Ehi, questa funzione non lo sta comunque modificando, quindi posso passare per riferimento e salvare alcuni cicli di clock." Non penso che farebbe mai una cosa del genere, dal momento che cambia la firma della funzione, ma rende il punto. Forse fa qualche manipolazione dello stack o qualcosa del genere ... Il punto è che non lo so, ma so che cercare di essere più intelligente del compilatore mi fa solo vergognare.

Il C ++ ha qualche bagaglio extra, con l'idea di cost-correct, quindi diventa ancora più importante.




Io uso const se posso. Const per i parametri significa che non dovrebbero cambiare il loro valore. Questo è particolarmente utile quando si passa per riferimento. const per function dichiara che la funzione non dovrebbe cambiare i membri delle classi.




Riassumere:

  • "Normalmente il valore di passaggio const è inutile e fuorviante al meglio." Da here
  • Ma puoi aggiungerli in .cpp come faresti con le variabili.
  • Si noti che la libreria standard non usa const. Ad esempio, std::vector::at(size_type pos) . Ciò che è abbastanza buono per la libreria standard è buono per me.



la cosa da ricordare con const è che è molto più facile rendere le cose fin dall'inizio, piuttosto che provare a inserirle in seguito.

Usa const quando vuoi che qualcosa rimanga invariato: è un suggerimento aggiunto che descrive cosa fa la tua funzione e cosa ti aspetti. Ho visto molte API C che potrebbero fare con alcune di esse, specialmente quelle che accettano c-stringhe!

Sarei più propenso ad omettere la parola chiave const nel file cpp rispetto all'intestazione, ma dato che tendo a tagliarli + incollarli, sarebbero tenuti in entrambe le posizioni. Non ho idea del perché il compilatore lo consenta, immagino sia una cosa del compilatore. La migliore pratica è sicuramente quella di mettere la tua parola chiave const in entrambi i file.




Il parametro Const è utile solo quando il parametro viene passato per riferimento ovvero, riferimento o puntatore. Quando il compilatore vede un parametro const, si assicura che la variabile utilizzata nel parametro non sia modificata all'interno del corpo della funzione. Perché qualcuno dovrebbe voler rendere costante un parametro di valore? :-)




Tutti i contenuti dei tuoi esempi non hanno scopo. C ++ è pass-by-value per impostazione predefinita, quindi la funzione ottiene copie di tali valori e booleani. Anche se la funzione li modifica, la copia del chiamante non è influenzata.

Quindi eviterei le Sali in più perché

  • Sono ridondanti
  • Ingombrano il testo
  • Mi impediscono di modificare il valore passato nei casi in cui potrebbe essere utile o efficiente.



Essendo un programmatore VB.NET che deve utilizzare un programma C ++ con oltre 50 funzioni esposte e un file .h che utilizza sporadicamente il qualificatore const, è difficile sapere quando accedere a una variabile utilizzando ByRef o ByVal.

Ovviamente il programma ti dice generando un errore di eccezione sulla linea in cui hai commesso l'errore, ma poi devi indovinare quale dei 2-10 parametri è sbagliato.

Così ora ho il compito spiacevole di provare a convincere uno sviluppatore che dovrebbero veramente definire le loro variabili (nel file .h) in un modo che permetta un metodo automatico di creare facilmente tutte le definizioni delle funzioni VB.NET. Allora diranno compiaciuti "leggi la ... documentazione".

Ho scritto uno script awk che analizza un file .h e crea tutti i comandi Declare Function, ma senza un indicatore su quali variabili sono R / O vs R / W, fa solo metà del lavoro.

MODIFICARE:

All'incoraggiamento di un altro utente, aggiungo quanto segue;

Ecco un esempio di una voce (IMO) di scarsa qualità .h;

typedef int (EE_STDCALL *Do_SomethingPtr)( int smfID, const char* cursor_name, const char* sql );

Il VB risultante dal mio script;

    Declare Function Do_Something Lib "SomeOther.DLL" (ByRef smfID As Integer, ByVal cursor_name As String, ByVal sql As String) As Integer

Nota il "const" mancante sul primo parametro. Senza di esso, un programma (o un altro sviluppatore) non ha Idea il primo parametro deve essere passato "ByVal". Aggiungendo "const", il file .h si auto-documenta in modo che gli sviluppatori che utilizzano altri linguaggi possano facilmente scrivere codice funzionante.




Related


Tags

c++   const