2012-12-16 15 views
7

Si consideri il seguente codice:Il binding temporaneo a un riferimento richiede un costruttore di copia in C++?

class A { 
    A(const A&); 
public: 
    A() {} 
}; 

int main() { 
    const A &a = A(); 
} 

Questo codice compila bene con GCC 4.7.2, ma non riesce a compilare con Visual C++ 2010 con il seguente errore:

test.cc(8) : error C2248: 'A::A' : cannot access private member declared in class 'A' 
     test.cc(2) : see declaration of 'A::A' 
     test.cc(1) : see declaration of 'A' 

Così è necessario avere un costruttore di copia accessibile quando si associa un riferimento temporaneo a un riferimento?

Questo è in qualche modo legato alla mia domanda precedente:

Is there a way to disable binding a temporary to a const reference?

+0

Sì, il copy ctor è privato e non implementato intenzionalmente. – vitaut

+0

Hai provato solo 'A(). 'È possibile che sia necessario che il costruttore di copia copi dalla funzione al valore restituito. –

+0

Visual C++ 2012 accetta il codice. –

risposta

4

So is it necessary to have a copy constructor accessible when binding a temporary to a reference?

Messaggio C++ 11 - No
Pre C++ 11 - Sì.


Questo codice si compila bene con GCC 4.7.2 perché è conforme allo standard C++ 11.

C++ 11 indica che quando un riferimento const viene inizializzato da prvalue, deve essere associato direttamente all'oggetto di riferimento e non è consentito creare alcun temporaneo. Inoltre, il costruttore di copie non viene utilizzato o richiesto.

Prima di C++ 11 le regole erano diverse. E questo comportamento (se il costruttore di copie sarà chiamato) è definito dall'implementazione. C++ 03 ha permesso il richiamo del costruttore di copie durante il binding di un riferimento const a un riferimento temporaneo e quindi al C++ 11 il costruttore di copie deve essere accessibile. Visual C++ 2010 aderisce allo standard C++ 03.

+0

"E questo comportamento è stato definito dall'implementazione" è un po 'fuorviante. La copia effettiva o meno era definita dall'implementazione, ma lo standard C++ 03 richiedeva un costruttore di copia accessibile. –

+0

@ Cheersandhth.-Alf: modificato per renderlo più chiaro. –

+1

"Lo standard C++ 11 stabilisce che quando un riferimento const viene inizializzato dal valore di prvalue, deve essere associato direttamente all'oggetto di riferimento e non è consentito creare alcun temporaneo." noi un po 'fuorvianti. Sostiene solo quando i tipi sono tali da rendere possibile il legame diretto. In altre parole, le regole non precludono una conversione. –

0

Visual C++ non è corretto; lo standard non indica che il costruttore di copia deve essere accessibile per associare un riferimento a const a un riferimento temporaneo.

2

sezione 8.5.3.5 degli stati standard C++ 03 che questo è definito dall'implementazione:

If the initializer expression is an rvalue, with T2 a class type, and "cv1 T1" is reference-compatible with "cv2 T2," the reference is bound in one of the following ways (the choice is implementation-defined):

-- The reference is bound to the object represented by the rvalue (see 3.10) or to a sub-object within that object.

-- A temporary of type "cv1 T2" [sic] is created, and a constructor is called to copy the entire rvalue object into the temporary. The reference is bound to the temporary or to a sub-object within the temporary.

The constructor that would be used to make the copy shall be callable whether or not the copy is actually done.

Così sembra che entrambe le implementazioni sono in linea con lo standard C++ 03.

L'ultima frase è un po 'confusa, ma il modo in cui l'ho letta, significa che l'implementazione può scegliere il secondo modo, ma ottimizzare ancora la copia. In tal caso, il costruttore di copie dovrebbe essere accessibile anche se la copia non è stata effettivamente eseguita, in modo simile all'ottimizzazione del valore di ritorno.

Con lo standard C++ 11, il secondo modo non è più un'opzione.

+4

C++ 03 è stato sostituito da C++ 11 e le regole sono cambiate in C++ 11. –

+0

Giusto, questo è quello che stavo cercando. Grazie. – vitaut

+0

@Vaughn Cato: l'unica cosa è che la tua ultima affermazione contraddice l'ultima affermazione dello standard che citi. Lo standard IIUC dice che il copy ctor dovrebbe essere disponibile in entrambi i casi, quindi GCC potrebbe usare le regole del nuovo standard o un bug. – vitaut

Problemi correlati