Hai năm sau, tôi hiểu tình hình tốt hơn nhiều, vì lợi ích của việc giữ các câu trả lời tràn ngăn xếp có liên quan và cập nhật ở đây là cách tôi sẽ trả lời câu hỏi ngày hôm nay.
Tiền đề của câu hỏi ban đầu của tôi có phần thiếu sót. Lý do để sử dụng thành ngữ pimpl là để ẩn các chi tiết thực hiện từ trình biên dịch. Điều này được thực hiện bằng cách lưu trữ việc thực hiện thông qua một con trỏ mờ (con trỏ đến một kiểu dữ liệu đã được khai báo nhưng không được xác định). Điều này có thể làm giảm đáng kể số lượng tiêu đề cần thiết bởi các đơn vị biên dịch khác tương tác với lớp và do đó tăng tốc thời gian biên dịch. Trong trường hợp mẫu trong câu hỏi của tôi, kiểu T được biết đầy đủ tại thời điểm diễn giải mà trong thực tế đòi hỏi kiểu của impl được định nghĩa đầy đủ ở bất cứ nơi nào C<ImplType>
được sử dụng làm cho điều này rõ ràng không phải là một ví dụ về thành ngữ pimpl theo nghĩa cổ điển của thuật ngữ.
Có nhiều lý do khác để giữ dữ liệu lớp học thông qua một con trỏ riêng, ví dụ nó cho phép dễ dàng thực hiện di chuyển và hoán đổi không ném và cũng tốt nếu lớp của bạn cần thực hiện bảo đảm ngoại lệ mạnh mẽ (xem bản sao và hoán đổi thành ngữ What is the copy-and-swap idiom?). Mặt khác, nó bổ sung thêm một lớp indirection (thường dẫn đến một lỗi cache) trên mọi truy cập vào impl và phân bổ đống/deallocation khi tạo và phá hủy impl.Đây có thể là hình phạt hiệu suất đáng kể, do đó giải pháp này không nên được coi là một viên đạn bạc.
Nếu bạn có thể sử dụng C++ 11 thì std :: unique_ptr nên được sử dụng thay vì tăng :: scoped_ptr.
Loại triển khai PIMPL này không có ý nghĩa gì bởi vì để khởi tạo mẫu C bạn phải biết về loại T. PIMPL, mặt khác, ẩn hoàn toàn tương đương với T từ người dùng. –
@VladLazarenko Hmm, tôi nghĩ tăng :: scoped_ptr hoạt động tốt trên các lớp được khai báo trước. Trong trường hợp này, nó phụ thuộc nếu T được xác định hoặc được khai báo trước. Bản sao của scoped_ptr này sẽ bị ẩn trong quá trình thực hiện (pimpl_ (new T()) –
@DavidFeurle: Không thực sự, để template này hoạt động, kích thước của 'T', cũng như giao diện của nó, phải tiếp xúc, bởi vì "khách hàng" cần phải nhanh chóng mẫu. Ví dụ, nơi bạn gọi là 'mới T()'? Bạn không thể ẩn nó trong "cpp" tập tin bởi vì nó phải được trong mẫu.Vì vậy, nó không phải là PIMPL. –