2012-02-08 14 views
9

Nel libro Deitel C++ ("C++ 11 per programmatori", p.286), non v'è un esempio di:Perché il passaggio per riferimento coinvolge un costruttore di copie?

class Date { ... } 

class Employee { 
public: 
    Employee(const string &, const string &, const Date &, const Date &); 
private: 
    string firstName; 
    string lastName; 
    const Date birthDate; 
    const Date hireDate; 
} 

Employee::Employee(const string &first, const string &last, 
    const Date &dateOfBirth, const Data &dateOfHire) 
    : firstName(first), 
    lastName(last), 
    birthDate(dateOfBirth), 
    hireDate(dateOfHire) { }; 

Il libro dice l'inizializzatore membro come birthDate(dateOfBirth) invocato costruttore di copia Date della classe. Sono confuso sul perché copiare il costruttore? Ho pensato che l'intero punto di "passare per riferimento" è quello di evitare la copia dell'oggetto?

Se lo faccio:

Date birth(7,24, 1959); 
Date hire(2,12, 1988); 
Employer staff("bob", "blue", birth, hire); 

Quanti Data oggetti fa il sistema ha ora, 2 o 4? (Due creati all'inizio, due sono creati dal costruttore di copie)

risposta

13

Non è la modalità di passaggio che implica una copia.

E 'l'inizializzazione dei membri che invove una copia (ovviamente i parametri non vivono nella classe, e ai membri della classe hanno bisogno di ottenere lo stesso valore:? Copia)

Esaminiamo

Employee::Employee(const string &first, const string &last, 
    const Date &dateOfBirth, const Data &dateOfHire) 
    : firstName(first), 
    lastName(last), 
    birthDate(dateOfBirth), 
    hireDate(dateOfHire) { }; 

// 
int main() 
{ 
    const std::string fname = "test"; 
    Employee e(fname, /* ..... */); 
} 
  1. invochiamo Employee::Employee, passando da fnameconst& (nessuna copia).
  2. Il costruttore inizializza è membro cognome dal primo parametro
  3. Questo esercita std::string(const std::string&), ancora una volta passando il parametro da const& (ancora nessuna copia).
  4. Il costruttore di copie std::string ora esegue tutti i passaggi necessari per copiare il valore del suo parametro nell'oggetto stesso. Questa è la copia

E 'logico che quando si costruisce un nuovo std::string (in questo caso come membro del dipendente), si traduce in un ... std::string nuova. Pensare in questo modo lo rende molto facile da capire, penso.

+0

così, ci sono infatti 2 nuovo oggetto Date creato da l'atto di costruttore di copia, così come nuovo oggetto di std: sono create stringa, sto capendo che hai ragione?grazie – Oliver

+0

In questo caso, le istanze dell'oggetto vengono visualizzate come membri della classe Employee e sono semplicemente _initialized_ (dai loro costruttori di copia) sul posto. Ma logicamente, sì, tutti questi membri sono inizializzati per diventare copie dei rispettivi inizializzatori ** e ** hanno appena iniziato la vita, assegnati come parte dell'oggetto Dipendente. ** Un impiegato ha una stringa, una stringa, una data, una data **, per così dire – sehe

2

Il punto di "passare per riferimento" è quello di non effettuare una copia non appena viene chiamato il costruttore Employee, ma solo quando si sceglie di inizializzare uno dei membri del dipendente con la data passata.

+0

formulati sinteticamente, +1. Nitpick: nessun compito è coinvolto, dal momento che i membri sono _initializzati_ dall'elenco di inizializzazione. – sehe

+1

C++, sempre il meglio per mettere il piede in bocca. – Rhangaun

+2

Non sono sicuro di cosa intendessi, ma ti assicuro che l'ho detto con buon umore :) Personalmente ritengo (troppo?) Che seguire la terminologia corretta sia noioso e talvolta _meh, ma è l'unico modo per costruire un approfondimento comprensione (in quale altro modo dovresti _know_ quando viene invocato un costruttore di copia, o meglio l'operatore di assegnazione? Questo è roba rilevante, e potrebbe essere uno stopper se la tua classe contenesse membri di riferimento.) Comunque, sto diventando fuori tema . Saluti – sehe

3

L'oggetto originale birth viene effettivamente passato con riferimento al costruttore di copie Employee, quindi non viene eseguita alcuna copia in tale fase. Tuttavia, quando la copia Employee viene constructred, il membroEmployee::birthDate scopo viene inizializzato utilizzando proprio costruttore di copia, per cui l'birth oggetto esterno viene passato per riferimento, ma che costruttore di copia sarà ovviamente effettuare una copia del birth oggetto, che diventa l'oggetto membro Employee::birthDate.

4

Queste due linee stanno per richiamare costruttore di copia del Data:

birthDate(dateOfBirth), 
hireDate(dateOfHire) 
Problemi correlati