2010-01-30 65 views
7

Trên trang 6 của Scott Meyers Hiệu quả C++, thuật ngữ 'hàm tạo bản sao' được định nghĩa. Tôi đã sử dụng cuốn sách của Schiltdt như là tài liệu tham khảo của tôi và tôi có thể tìm thấy không đề cập đến các nhà xây dựng sao chép. Tôi có được ý tưởng nhưng đây có phải là một phần tiêu chuẩn của C++? Các nhà xây dựng như vậy có được gọi khi vượt qua một lớp theo giá trị không?Một hàm tạo bản sao trong C++ là gì?

+12

Vâng, đó sẽ là điển hình của Schildt - tại sao trên trái đất để mọi người sử dụng cuốn sách của ông? –

+4

Xin đừng lấy sách của Schildt mà không có một chút muối. Google cho thuật ngữ "Bullschildt" và tự mình xem. Nghiêm túc hơn, đọc các bài đánh giá về sách của Schildt về ACCU; hầu hết trong số họ không thuận lợi. –

+1

@Neil: mặc dù tôi cũng đã nghe những điều xấu về sách của Schildt, nhưng thật khó tin * rằng nó không nói về các nhà xây dựng bản sao. –

Trả lời

9

Bản sao constructor có dạng sau:

class example 
{ 
    example(const example&) 
    { 
     // this is the copy constructor 
    } 
} 

Ví dụ sau đây cho thấy nơi nó được gọi.

void foo(example x); 

int main(void) 
{ 
    example x1; //normal ctor 
    example x2 = x1; // copy ctor 
    example x3(x2); // copy ctor 

    foo(x1); // calls the copy ctor to copy the argument for foo 

} 
+2

Chỉ khi 'foo' có nguyên mẫu' void foo (ví dụ x); '. Ví dụ, 'void foo (const example & x);' sẽ không gọi bất kỳ hàm tạo nào. Hoặc 'void foo (int x);' có thể gọi một toán tử cast 'operator int()' nếu không phải là lỗi trình biên dịch – kennytm

+1

Tôi đã sửa đổi bài viết để bao gồm các mẫu thử nghiệm cho foo(), để làm cho nó rõ ràng. – DerKuchen

+0

-1 "Một nhà xây dựng bản sao có dạng sau:" là không chính xác. Có bốn hình thức có thể của bản sao constructor. Ngoài ra ví dụ lớp là cú pháp không hợp lệ –

14

Có, các nhà xây dựng sao chép chắc chắn là một phần thiết yếu của tiêu chuẩn C++. Đọc thêm về họ (và các nhà thầu khác) here (C++ FAQ).

Nếu bạn có một cuốn sách C++ không dạy về các nhà xây dựng sao chép, hãy vứt bỏ nó đi. Đó là một cuốn sách tồi.

4

Xem Copy constructor trên Wikipedia.

Ý tưởng cơ bản là nhà xây dựng bản sao nhanh chóng các trường hợp mới bằng cách sao chép những cái hiện có:

class Foo { 
    public: 
    Foo();    // default constructor 
    Foo(const Foo& foo); // copy constructor 

    // ... 
}; 

Với một thể hiện foo, gọi constructor sao chép với

Foo bar(foo); 

hoặc

Foo bar = foo; 

Các thùng chứa của Thư viện Mẫu Tiêu chuẩn yêu cầu các đối tượng t o có thể sao chép và gán, vì vậy nếu bạn muốn sử dụng std::vector<YourClass>, hãy đảm bảo xác định một hàm tạo bản sao thích hợp và operator= nếu các giá trị mặc định do trình biên dịch tạo ra không có ý nghĩa.

0

Liên kết C++ FAQ được đăng bởi Eli là bài đăng đẹp và gbacon là chính xác.

Để trả lời một cách rõ ràng phần thứ hai của câu hỏi của bạn: có, khi bạn chuyển một đối tượng theo giá trị, hàm tạo bản sao sẽ được sử dụng để tạo cá thể cục bộ của đối tượng trong phạm vi của cuộc gọi hàm. Mỗi đối tượng có một "hàm tạo bản sao mặc định" (gbacon ám chỉ điều này là "trình biên dịch tạo mặc định") mà chỉ sao chép từng thành viên đối tượng - điều này có thể không phải là những gì bạn muốn nếu đối tượng của bạn chứa con trỏ hoặc tham chiếu.

Về những cuốn sách tốt để học lại C++ - lần đầu tiên tôi học nó gần hai thập kỷ trước và nó đã thay đổi rất nhiều kể từ đó - tôi khuyên bạn nên sử dụng phiên bản 1 và 2 của Bruce Eckel. trong cả hai PDF và hình thức HTML):

http://www.ibiblio.org/pub/docs/books/eckel/

2

Sao chép constructor sẽ được gọi trong các tình huống sau đó sau:

  • Khi tạo đối tượng mới từ một đối tượng hiện có.

    MyClass Obj1; 
    MyClass Obj2 = Obj1; // Here assigning Obj1 to newly created Obj2 
    

    hoặc

    MyClass Obj1; 
    MyClass Obj2(Obj1); 
    
  • Khi đi qua đối tượng lớp theo giá trị.

    void NewClass::TestFunction(MyClass inputObject_i) 
    { 
        // Function body 
    } 
    

    Đối tượng MyClass phía trên được truyền theo giá trị. Vì vậy, sao chép constructor của MyClass sẽ gọi. Vượt qua tham chiếu để tránh gọi hàm sao chép.

  • Khi trở về đối tượng theo giá trị

    MyClass NewClass::Get() 
    { 
        return ObjMyClass; 
    } 
    

    Trên MyClass được trả lại theo giá trị, Vì vậy, copy constructor của MyClass sẽ gọi. Vượt qua tham chiếu để tránh gọi hàm sao chép.

1

Sao chép Constructor là một phần thiết yếu của C++. Mặc dù bất kỳ trình biên dịch C++ nào đều cung cấp hàm tạo bản sao mặc định nếu ở tất cả nếu chúng ta không định nghĩa nó một cách rõ ràng trong lớp, chúng ta viết constructor sao chép cho lớp vì hai lý do sau đây.

  1. Nếu có bất kỳ phân bổ bộ nhớ động nào trong lớp.
  2. Nếu chúng tôi sử dụng các biến con trỏ bên trong lớp học. (Nếu không nó sẽ trở thành một bản sao cạn trong mà 2 đối tượng sẽ trỏ đến vị trí bộ nhớ tương tự.)

Để tạo một bản sao sâu, bạn phải viết một constructor sao chép và quá tải toán tử gán, nếu không sao chép sẽ chỉ vào bản gốc, với hậu quả tai hại.

Bản sao constructor cú pháp sẽ được viết như sau:

class Sample{ 

public: 
    Sample (const Sample &sample); 

}; 

int main() 
{ 

    Sample s1; 
    Sample s2 = s1; // Will invoke Copy Constructor. 
    Sample s3(s1);  //This will also invoke copy constructor. 

    return 0; 
} 
Các vấn đề liên quan