Domanda

Ho letto e riletto le clausole rilevanti sull'ODR nello standard C++, ma questa domanda rimane ancora aperta per me.Lo standard dice che la definizione di una funzione inline deve apparire in ogni unità di traduzione in cui viene utilizzata, e le definizioni devono essere identiche nel senso descritto in quasi una pagina.Dice che la sequenza dei token deve essere la stessa.Include i nomi degli identificatori locali?

In altre parole il seguente programma viola l'ODR? (Ho provato a testarlo personalmente con Visual Studio 2008 e ho ricevuto 0 errori e 0 avvisi.Ma immagino che questo non dimostri nulla, perché ho poi cambiato l'esempio in due definizioni completamente diverse e ho comunque ottenuto 0 errori e 0 avvisi.A scusa della MSVC si precisa che non è formalmente richiesta alcuna diagnosi per le violazioni dell'ODR).

//main.cpp
inline int f(int);
int main(){
   f(3);
}
int f(int x){
   int z = x;
   return z*z;
}

//other.cpp
inline int f(int xx){
   int zz = xx;
   return zz*zz;
}
È stato utile?

Soluzione

L'identificatore è una sorta di token, ogni identificatore è un token separato, quindi sì, è necessario avere lo stesso identificatore per rispettare l'ODR.Può fare la differenza in un compilatore che rileva questo (qualcuno pronto a creare un esempio per Como con il modello esportato?può rilevare qualche violazione dell'ODR).

Quindi qui c'è una differenza tra C e C++.C non ha l'ODR in generale e le regole per la funzione inline in C99 (non ci sono funzioni inline in C90) sono abbastanza diverse da quelle di C++.In C99, il tuo codice è corretto.In effetti puoi fornire una definizione completamente diversa.Una conseguenza è che in C (ma non in C++), se si utilizza la stessa definizione e tale definizione ha un membro statico, si hanno in effetti tante variabili statiche quante sono le variabili statiche di TU che utilizza la funzione.

Altri suggerimenti

Sì, viola ODR. Esso utilizza diverse sequenze di token, non so cosa c'è di così difficile da capire qui.

Verifica ODR attraverso unità di traduzione è difficile (impossibile) con tecniche di compilazione tradizionali. Lo standard dice che "Nessun diagnostica necessari", quindi basta avere un comportamento non definito.

E 'possibile ottenere ancora più sottili errori quando si utilizza per esempio due classi differenti definite in unità di traduzione indipendenti ma con lo stesso nome. Se v'è una tabella virtuale può scontrarsi senza messaggi di errore (è successo al mio amico). Quindi, sempre usare un namespace anonimo per le funzioni e le classi locali.

Gli identificatori sono gettoni, quindi dalla stessa sequenza di token governare, il programma viola l'ODR.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top