2012-02-08 43 views
9

Trong Deitel C++ cuốn sách ("C++ 11 cho lập trình viên", p.286), có một ví dụ về:Tại sao truyền qua tham chiếu liên quan đến một hàm tạo bản sao?

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) { }; 

Cuốn sách nói initializer thành viên như birthDate(dateOfBirth) gọi constructor sao chép Date lớp của. Tôi bối rối là tại sao sao chép constructor? Tôi nghĩ rằng toàn bộ điểm "vượt qua bằng cách tham khảo" là để tránh các đối tượng sao chép?

Nếu tôi làm:

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

bao nhiêu ngày đối tượng nào hệ thống có bây giờ, 2 hoặc 4? (Hai được tạo khi bắt đầu, hai được tạo bởi hàm khởi tạo sao chép)

Trả lời

13

Đây không phải là chế độ truyền liên quan đến bản sao.

Đây là khởi tạo của các thành viên mà invove một bản sao (rõ ràng các thông số không sống trong lớp, và các thành viên lớp cần phải nhận được giá trị như nhau: bản sao)

Hãy kiểm tra

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. Chúng tôi gọi Employee::Employee, đi qua fname bởi const& (không sao chép).
  2. Hàm khởi tạo khởi tạo tên thành viên của nó từ tham số đầu tiên
  3. Bài tập này std::string(const std::string&), một lần nữa chuyển tham số theo const& (vẫn không sao chép).
  4. Nhà xây dựng bản sao std::string giờ đây thực hiện tất cả các bước cần thiết để sao chép giá trị của thông số của nó vào chính đối tượng đó. Đây là bản sao

Nó làm cho cảm giác rằng khi bạn xây dựng một mới std::string (trong trường hợp này là một thành viên của nhân viên), nó kết quả trong một ... mới std::string. Nghĩ về nó theo cách này làm cho nó rất dễ nắm bắt, tôi nghĩ vậy.

+0

như vậy, có thực sự là 2 đối tượng ngày mới được tạo ra bởi các hành động của constructor sao chép, cũng giống như đối tượng mới của std: string được tạo ra, Tôi hiểu bạn đúng không?thx – Oliver

+0

Trong trường hợp này, các cá thể đối tượng xuất hiện dưới dạng các thành viên của lớp Employee và chúng chỉ đơn thuần là _initialized_ (bởi các hàm tạo bản sao của chúng) tại chỗ. Nhưng về mặt logic, có, tất cả các thành viên này được khởi tạo để trở thành bản sao của các trình khởi tạo tương ứng của chúng ** và ** chúng vừa mới bắt đầu cuộc sống, được phân bổ như một phần của đối tượng Employee. ** Một nhân viên có một chuỗi, chuỗi, Ngày, Ngày **, do đó, để nói – sehe

2

Điểm "chuyển bằng tham chiếu" là không tạo bản sao ngay sau khi hàm tạo nhân viên được gọi, nhưng chỉ khi bạn chọn khởi tạo một thành viên của nhân viên với ngày đã qua.

+0

Được viết gọn gàng, +1. Nitpick: không có phép gán nào, vì các thành viên là _initialized_ từ danh sách khởi tạo. – sehe

+1

C++, luôn là cách tốt nhất để đặt chân vào miệng. – Rhangaun

+2

Tôi không chắc chắn ý bạn là gì, nhưng hãy yên tâm tôi đã nói điều đó trong tinh thần tốt :) Cá nhân tôi cảm thấy (quá?) Tôn trọng các thuật ngữ chính xác là nhàm chán và đôi khi, nhưng đó là cách duy nhất để xây dựng sâu hơn sự hiểu biết (làm cách nào khác bạn sẽ biết _know_ khi một hàm tạo bản sao được gọi, hay đúng hơn là toán tử gán? Đây là các công cụ có liên quan và có thể là một nút hiển thị nếu lớp của bạn chứa các thành viên tham chiếu.) . Chúc mừng – sehe

3

Đối tượng gốc của bạn birth thực sự được chuyển bằng cách tham chiếu đến hàm tạo bản sao Employee, do đó không có bản sao nào được thực hiện ở giai đoạn đó. Tuy nhiên, khi bản sao Employee đang được constructred, các viênEmployee::birthDate đối tượng được khởi tạo bằng cách sử dụng riêng constructor bản sao của nó, mà các đối tượng bên ngoài birth được thông qua tham khảo, nhưng điều đó copy constructor sẽ đương nhiên tạo một bản sao của birth đối tượng, trở thành đối tượng thành viên Employee::birthDate.

4

Hai dòng này sẽ gọi copy constructor của ngày:

birthDate(dateOfBirth), 
hireDate(dateOfHire) 
Các vấn đề liên quan