2013-07-03 15 views
5

io non riesco a capire il motivo per cui nel prossimo pezzo di codice, il constuctor copia definito non stampa ...C++ Copia Constructor Oddity

#include <iostream> 
using namespace std; 
class B { 
    static int count; 
    int data; 
    int id; 

    void print(const char* p) 
    { 
     cout <<p <<", "<<id <<", " << data << endl; 
    } 

    public: 

    B(int d=0) 
    { 
     data=d; id=++count; print("B(int)"); 
    } 
    B(const B& a) 
    { 
     data=a.data; id=++count; print("B(cost B&)"); 
    } 
    ~B(){print("~B()");} 

    operator bool(){ return (bool)data;} 
    B operator+(int i){print("operator+"); return B(data+i);} 
}; 


int B::count=0; 

void main(){ 
    B b(42); 
    B x=b+2; 
    bool z=b+1; 

    getchar(); 
} 

mi aspettavo di ottenere una stampa copia costruttore con B x=b+2 ma doesn mostrare. Qualche idea? Grazie,


L'output:

B(int), 1, 42 
operator+, 1, 42 
B(int), 2, 44 
operator+, 1, 42 
B(int), 3, 43 
~B(), 3, 43 

Quindi è l'ottimizzazione valore di ritorno?

+3

Probabilmente è stato eliminato. –

+0

Che compilatore stai usando? Se supporta C++ 11 dovresti avere un costruttore di movimento definito - vedi la Regola di cinque. –

+3

Vedere [copy elision] (http://en.wikipedia.org/wiki/Copy_elision). – juanchopanza

risposta

1

Ho inserito questo in GCC molto velocemente e ho notato lo stesso comportamento. Ovviamente il compilatore sta cambiando il comportamento del codice nel modo che ritiene opportuno.

Per uno: l'assegnazione non è uguale al costruttore di copie. Ho pensato che dal momento che stava usando '=' cercava un operatore = sovraccarico e non trovandolo e quindi scegliendo di creare un nuovo oggetto B usando il suo normale costruttore e poi copiandolo in x usando l'assegnazione predefinita. Funziona poiché è una classe semplice.

ho cambiato

B x=b+2; 

a

B x(b+2); 

per cercare di forzare per usare il costruttore di copia. Tuttavia ho avuto lo stesso comportamento. Ho quindi esaminato il tipo restituito dall'operatore + e ho notato che restituisce un B. (Non è un riferimento ma può essere valutato come riferimento purché rispetti le regole di riferimento precedenti a C++ 11). Quindi di nuovo il compilatore sta generando il codice nello stesso modo in cui lo ha fatto sopra, quindi non stiamo facendo uso del costruttore di copie.

Se si cambia

B x(b+2); 

a

B x(b); 

Il compilatore capisce che il costruttore di copia può essere utilizzato (aka è in grado di generare un riferimento a b).

La mia ipotesi è che il compilatore stia generando codice a causa del tipo di ritorno dell'operatore +. Probabilmente ha qualcosa a che fare con come i riferimenti non const vengono gestiti come lvalue solo in pre C++ 11. Quindi, poiché l'operatore + viene chiamato, non può creare da esso un riferimento const per passare al costruttore della copia (perché il risultato dell'operatore + è un lvalue). Quindi utilizza il costruttore regolare insieme a un operatore di assegnazione generato automaticamente per eseguire il lavoro richiesto.

Spero che questo aiuti.