Semantica C ++ di `static const` vs` const`


149

Nello specifico di C ++, quali sono le differenze semantiche tra ad esempio:

static const int x = 0 ;

e

const int x = 0 ;

sia staticcome collegamento che come identificatore della classe di archiviazione (ovvero all'interno e all'esterno di una funzione).


7
staticè probabilmente la parola chiave più sovraccarica in C ++. Il significato del codice varia ampiamente a seconda che si tratti dell'ambito dello spazio dei nomi, dell'ambito della classe o dell'ambito della funzione. Potresti volerlo chiarire.
sabato

1
@sbi: pensavo di averlo già fatto. Ambito della funzione (dove è un identificatore della classe di archiviazione) e ambito del file (dove è un identificatore del collegamento). I membri della classe e le variabili con ambito namespace non mi interessano in modo specifico rispetto a questa domanda, anche se se qualcuno ritiene che ci sia una distinzione interessante, sentiti libero di occuparsene anche tu.
Clifford,

@Clifford: mi dispiace di aver trascurato quelle ultime parole. Tuttavia, questo ha rivelato un malinteso da parte tua: in C ++, l'ambito dei file è l' ambito dello spazio dei nomi. Se dichiari qualcosa al di fuori di qualsiasi spazio dei nomi, apparirà semplicemente nello spazio dei nomi globale (ed è accessibile attraverso un prefisso ::senza identificatore davanti). Non sono a conoscenza di differenze significative tra lo spazio dei nomi globale e qualsiasi spazio dei nomi annidato in esso. Di certo non c'è nulla riguardo agli staticoggetti.
sbi,

1
il collegamento è diverso dalla visibilità , usandoli in modo intercambiabile confonderai le persone con cui parli e probabilmente anche te stesso.
Ben Voigt,

1
@Ben, @sbi: non intendevo suggerire che l' ambito dei file e il collegamento statico fossero gli stessi, ma semplicemente che il collegamento statico implica l' ambito dei file. In questo senso l' ambito (o la visibilità) è un attributo di collegamento statico ed esterno, non un sinonimo per nessuno dei due. Sento che la domanda originale rimane chiara e ben formata e che stiamo semplicemente discutendo i commenti fatti in risposta all'osservazione un po 'condiscendente di sbi. Stiamo discutendo la semantica imprecisa dell'inglese qui piuttosto che la mia comprensione, quindi penso che possiamo smettere.
Clifford,

Risposte:


128

Nell'ambito del file, nessuna differenza in C ++. constrende il collegamento interno predefinito e tutte le variabili globali hanno una durata statica. Ma la prima variante ha lo stesso comportamento in C, quindi potrebbe essere una buona ragione per usarla.

All'interno di una funzione, la seconda versione può essere calcolata dai parametri. In C o C ++ non deve essere una costante di compilazione come richiedono altre lingue.

All'interno di una classe, sostanzialmente la stessa cosa delle funzioni. È constpossibile calcolare un valore di istanza nell'elenco ctor-initializer-list . A static constviene impostato durante l'inizializzazione all'avvio e rimane invariato per il resto del programma. (Nota: il codice per i staticmembri sembra leggermente diverso perché la dichiarazione e l'inizializzazione sono separate.)

Ricorda, in C ++, constsignifica sola lettura , non costante . Se hai un puntatore a, constallora altre parti del programma possono cambiare il valore mentre non stai guardando. Se la variabile è stata definita con const, allora nessuno può cambiarla dopo l'inizializzazione ma l'inizializzazione può ancora essere arbitrariamente complessa.


1
Esiste qualcosa chiamato ambito file? Stavo solo controllando $ 3,3 e penso che il più vicino sia "scope dello spazio dei nomi". La mia comprensione è giusta? Lo standard C ++ 03 menziona l'ambito del file solo nelle Appendici
Chubsdad,

2
Vorrei suggerire che l' ambito dei file è un artefatto del linker piuttosto che del compilatore, quindi potrebbe non avere molta attenzione nello standard linguistico. È rigorosamente "ambito di unità di compilazione".
Clifford,

8
+1 per la frase "const significa sola lettura, non costante", ovvero "Compilatore, se vedi qualcuno che tenta di modificare questa const, abbaia molto forte." Questo è il motivo per cui qualcosa può essere costante e volatile allo stesso tempo.
Dan,

5
È più "Compilatore, se mi vedi provare a modificare questa const (o dare a qualcun altro il permesso di farlo)", abbaia molto forte. Nella maggior parte del contesto, si constapplica a una vista della variabile e non alla variabile stessa, qualcun altro può avere una mancata constvisualizzazione della stessa variabile e il compilatore rimarrà piuttosto silenzioso quando lo modificherà.
Ben Voigt,

1
@Ben: Giusto per essere chiari, C ++ 0x non rimuove quel particolare uso di const, ma il nuovo constexprpuò essere usato invece (e anche in altri scenari). In realtà, lo standard C ++ 0x espande la capacità di utilizzare constin quello scenario anche a "tipi letterali" non integrali. Penso che preferirei usare constexprper quei casi, dato che avresti comunque rotto la retrocompatibilità con i compilatori pre-C ++ 0x.
Michael Burr,

4

La bozza standard di C ++ 17 constimplica staticnell'ambito del file

Questa è la citazione per quanto menzionato in: https://stackoverflow.com/a/3709257/895245

Progetto standard C ++ 17 n4659 6.5 "Programma e collegamento":

3 Un nome con ambito dello spazio dei nomi (6.3.6) ha un collegamento interno se è il nome di

  • (3.1) - una variabile, funzione o modello di funzione esplicitamente dichiarato statico; o,
  • (3.2) - una variabile non inline di tipo const non volatile non dichiarata esplicitamente esternamente o precedentemente dichiarata con collegamento esterno; o
  • (3.3) - un membro dei dati di un'unione anonima.

Allegato C (informativa) Compatibilità, C.1.2 Clausola 6: "concetti di base" fornisce la logica per cui è stato modificato da C:

6.5 [anche 10.1.7]

Modifica: un nome di ambito file dichiarato esplicitamente const e non esplicitamente dichiarato esternamente ha un collegamento interno, mentre in C avrebbe un collegamento esterno.

Motivazione: Poiché gli oggetti const possono essere utilizzati come valori durante la traduzione in C ++, questa funzione sollecita i programmatori a fornire un inizializzatore esplicito per ogni oggetto const. Questa funzione consente all'utente di inserire oggetti const nei file di origine inclusi in più di un'unità di traduzione.

Effetto sulla funzione originale: passa alla semantica della funzione ben definita.

Difficoltà di conversione: trasformazione semantica.

Come ampiamente usato: Di rado.

Vedi anche: Perché const implica un collegamento interno in C ++, quando non in C?

Quello che probabilmente vorresti fare invece sulle intestazioni

Spiegato in dettaglio in: Cosa significa "const static" in C e C ++?

  • pre C ++ 17: externnell'intestazione, definizione nel file cpp
  • post C ++ 17: variabile incorporata nell'intestazione

Grazie, anche se non penso che questa sia una possibilità in C ++ 17 rispetto anche a C ++ 98, e la domanda è stata posta nel 2010. Inoltre, la tua risposta si occupa solo di static come specificatore di collegamenti (nell'ambito dello spazio dei nomi) e la domanda posta specificamente sulla semantica in contesti diversi.
Clifford,

@Clifford sì, sicuramente più vecchio di C ++ 17, solo pigro per leggere tutti gli standard ;-) Chiarirà la parte dell'ambito del file.
Ciro Santilli 26 冠状 病 六四 事件 法轮功
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.