[C++] Uso di 'const' per i parametri di funzione


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).

Question

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.




Se usi gli operatori ->* o .* , È obbligatorio.

Ti impedisce di scrivere qualcosa di simile

void foo(Bar *p) { if (++p->*member > 0) { ... } }

che ho quasi fatto adesso, e che probabilmente non fa quello che intendi.

Quello che intendevo dire era

void foo(Bar *p) { if (++(p->*member) > 0) { ... } }

e se avessi messo un const tra Bar * e p , il compilatore me lo avrebbe detto.




Marcare i parametri del valore 'const' è sicuramente una cosa soggettiva.

Tuttavia in realtà preferisco contrassegnare i parametri di valore const, proprio come nel tuo esempio.

void func(const int n, const long l) { /* ... */ }

Il valore per me indica chiaramente che i valori dei parametri della funzione non vengono mai modificati dalla funzione. Avranno lo stesso valore all'inizio come alla fine. Per me, fa parte del mantenere uno stile di programmazione molto funzionale.

Per una funzione breve, è indubbiamente uno spreco di tempo / spazio avere il 'const' lì, dato che di solito è abbastanza ovvio che gli argomenti non vengono modificati dalla funzione.

Tuttavia, per una funzione più ampia, è una forma di documentazione di implementazione e viene applicata dal compilatore.

Posso essere sicuro che se faccio un calcolo con 'n' e 'l', posso refactoring / spostare quel calcolo senza paura di ottenere un risultato diverso perché ho perso un posto in cui uno o entrambi sono cambiati.

Poiché si tratta di un dettaglio di implementazione, non è necessario dichiarare i parametri value const nell'intestazione, proprio come non è necessario dichiarare i parametri di funzione con gli stessi nomi utilizzati dall'implementazione.




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.




Being a VB.NET programmer that needs to use a C++ program with 50+ exposed functions, and a .h file that sporadically uses the const qualifier, it is difficult to know when to access a variable using ByRef or ByVal.

Of course the program tells you by generating an exception error on the line where you made the mistake, but then you need to guess which of the 2-10 parameters is wrong.

So now I have the distasteful task of trying to convince a developer that they should really define their variables (in the .h file) in a manner that allows an automated method of creating all of the VB.NET function definitions easily. They will then smugly say, "read the ... documentation."

I have written an awk script that parses a .h file, and creates all of the Declare Function commands, but without an indicator as to which variables are R/O vs R/W, it only does half the job.

MODIFICARE:

At the encouragement of another user I am adding the following;

Here is an example of a (IMO) poorly formed .h entry;

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

The resultant VB from my script;

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

Note the missing "const" on the first parameter. Without it, a program (or another developer) has no Idea the 1st parameter should be passed "ByVal." By adding the "const" it makes the .h file self documenting so that developers using other languages can easily write working code.




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



Non metterei costanti su parametri come questo - tutti sanno già che un booleano (al contrario di un booleano e) è costante, quindi aggiungerlo farà sì che la gente pensi "aspetta, cosa?" o anche che stai passando il parametro per riferimento.




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 .




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.




Non uso const per parametere passato valore. Al chiamante non importa se si modifica il parametro o meno, si tratta di un dettaglio di implementazione.

Ciò che è veramente importante è contrassegnare i metodi come const se non modificano la loro istanza. Fai questo mentre vai, perché altrimenti potresti finire con un sacco di const_cast <> o potresti scoprire che marcare un metodo const richiede di cambiare molto codice perché chiama altri metodi che dovrebbero essere stati marcati const.

Tendo anche a contrassegnare vars const locali se non ho bisogno di modificarli. Credo che faciliti la comprensione del codice rendendo più facile l'identificazione delle "parti mobili".




All the consts in your examples have no purpose. C++ is pass-by-value by default, so the function gets copies of those ints and booleans. Even if the function does modify them, the caller's copy is not affected.

So I'd avoid extra consts because

  • They're redudant
  • They clutter up the text
  • They prevent me from changing the passed in value in cases where it might be useful or efficient.






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? :-)




There's really no reason to make a value-parameter "const" as the function can only modify a copy of the variable anyway.

The reason to use "const" is if you're passing something bigger (eg a struct with lots of members) by reference, in which case it ensures that the function can't modify it; or rather, the compiler will complain if you try to modify it in the conventional way. It prevents it from being accidentally modified.




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 relative alle prestazioni.

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