Il commento nelle FAQ è molto fuorviante; sia AE::c6
e AE::c7
sono lvalue. Se non esiste una definizione di AE::c7
, il codice in questione viola la regola una sola definizione:
An expression is potentially evaluated unless it is an unevaluated operand or a subexpression thereof. A variable whose name appears as a potentially-evaluated expression is odr-used unless it is an object that satisfies the requirements for appearing in a constant expression and the lvalue-to-rvalue conversion is immediately applied. [...]
[...]
Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; no diagnostic required.
In pratica, il linker generalmente genererà un errore se il compilatore in realtà necessario l'indirizzo dell'oggetto. Nel tuo caso , se il p2
non viene utilizzato in seguito, il compilatore non avrà bisogno dell'indirizzo , poiché l'ottimizzazione rimuoverà la definizione di p1
. Un caso ancora più frequente in cui questo avviene sono cose come il seguenti:
std::vector<int> v;
v.push_back(AE::c6);
Da std::vector<>::push_back
prende un riferimento, non c'è immediata conversione Ivalue a rvalue e una definizione è richiesto. In pratica, std::vector<>::push_back
è una funzione modello (di solito in linea), quindi il compilatore può vedere nella sua implementazione e propagare il valore nella funzione nel punto in cui si verifica la conversione da lvalue a valore effettivo in realtà e il codice verrà compilato e funzionerà. Ma è ancora comportamento formalmente indefinito.
fonte
2014-06-19 09:41:13
Cosa succede se si compila 'classe AE' e' f() 'separatamente e quindi si collegano gli oggetti? – juanchopanza
@juanchopanza Si compila con '-O2' e' f() 'è essenzialmente un nop. Tuttavia, fornisce un errore del linker con '-O0', come il programma originale con' -O0'. – Csq
@Csq Sì, ho visto e ho votato la tua risposta. In alternativa, 'std :: cout << p1 << std :: endl;' farebbe in un op. – juanchopanza