2014-10-01 14 views
14

tôi đang đánh giá trang cppreference về nhà xây dựng bản sao ở đây: http://en.cppreference.com/w/cpp/language/copy_constructorSự khác biệt giữa các nhà xây dựng bản sao được khai báo ngầm định và ngầm định là gì?

Tôi đã đọc 2 phần về nhà xây dựng bản sao ngầm-tuyên bố và nhà thầu sao chép ngầm định nghĩa khá một vài lần nhưng tôi vẫn không hiểu phân biệt. Sẽ không phải là một tuyên bố ngầm nhưng không được định nghĩa kết quả xây dựng trong các vấn đề liên kết?

Quy tắc rất phức tạp. Tôi không nhớ có một sự khác biệt trong C++ 03: Hoặc bạn đã có một trình biên dịch tạo ra bản sao constructor hoặc bạn đã không.

Ai đó có thể giải thích (theo những từ đơn giản hơn) sự khác biệt/khác biệt giữa hai loại này là gì?

Trả lời

11

này được làm sáng tỏ trong một lưu ý trong tiêu chuẩn ở phần đầu của khoản 12:

[Lưu ý: Việc thực hiện sẽ mặc nhiên tuyên bố các chức năng này thành viên đối với một số loại lớp khi chương trình thực hiện không tuyên bố rõ ràng. Việc thực hiện sẽ ngầm định nghĩa chúng nếu chúng được sử dụng odr (3.2). Xem 12.1, 12.4 và 12.8. - cuối note]

Tài liệu viện dẫn cho C++ 14 (N3936) là 12,1/5, 12,4/6, 12,8/13, 12,8/26.Trong mỗi trường hợp, hàm thành viên đặc biệt tương ứng được xác định ngầm định nếu nó được mặc định và không được định nghĩa là đã xóa, và được sử dụng hoặc được mặc định một cách rõ ràng. Nếu chúng ta có một cái gì đó giống như

struct Foo {}; 

và không có đối tượng thuộc loại Foo được từng được tạo ra, tất cả sáu thành viên chức năng đặc biệt (constructor mặc định, destructor, copy constructor, di chuyển nhà xây dựng, sao chép toán tử gán, di chuyển tử gán) đều được ngầm tuyên bố như mặc định, nhưng không được định nghĩa vì chúng không được sử dụng odr.

+1

Giải thích rất tuyệt vời. Tôi rất muốn xem các ví dụ khác về các kịch bản khác nhau kết hợp khai báo ngầm với các tình huống khác đã bị xóa/ngầm định/tầm thường. –

3

Nếu có một hàm tạo bản sao được khai báo ngầm, nó luôn được xác định . Các tùy chọn cho định nghĩa của nó là:

  • xóa
  • tầm thường
  • ngầm xác định

Nếu một chương trình cố gắng sử dụng một constructor được định nghĩa là xóa sau đó chương trình là vô hình thành (tức là bạn nhận được một lỗi trình biên dịch). Trong các trường hợp khác, hàm được gọi.

Trang bạn liên kết mô tả trong đó các tình huống mà mỗi trong ba tùy chọn ở trên xảy ra.

C++ 11 thêm khái niệm hàm delete d, khi bạn muốn làm cho lớp không thể sao chép được một cách rõ ràng (v.v.). Bạn xác định bản sao của nó-constructor như đã xóa và sau đó trình biên dịch tạo ra một lỗi nếu ai đó cố gắng để sao chép đối tượng của bạn.

Sự khác biệt giữa có thể sao chép một cách đáng kể và không đáng kể có thể sao chép được luôn ở đó nhưng không được nêu rõ quá rõ ràng; bạn suy ra từ các quy tắc về POD, trong đó các tình huống được phép sử dụng memcpy để sao chép các đối tượng.

Như Brian đã chỉ ra, chính xác hơn là nói được xác định nếu được yêu cầu. Trình biên dịch không bao giờ ngầm khai báo một hàm và sau đó tạo ra một lỗi liên kết. Nhưng nếu định nghĩa hàm không cần thiết để xây dựng thành công tệp thực thi, nó sẽ không bận tâm thực sự tạo ra định nghĩa.

+0

Có thể tôi đã hiểu sai nhưng khai báo là tập hợp con các định nghĩa. Nói cách khác, nếu một cái gì đó được định nghĩa thì nó cũng được khai báo. Tuy nhiên, nếu một cái gì đó được tuyên bố rằng không có nghĩa là nó được định nghĩa (do đó chúng tôi đã nói nó đã được xác định) –

+1

@ void.pointer Bạn đang nói về các cấu trúc cú pháp do người dùng cung cấp. Đây là nói về các hàm tạo được trình biên dịch tạo ra. Trình biên dịch không bao giờ ngầm khai báo một hàm mà không định nghĩa nó (tốt - như Brian đã chỉ ra, trình biên dịch sẽ không bận tâm để tạo ra định nghĩa nếu nó không bao giờ thực sự được gọi). –

Các vấn đề liên quan