2014-09-03 20 views
7

Tôi không thể hiểu cách shared_ptr có thể lưu trữ deleter mà tôi đã cung cấp cho nó như thế nào.Làm thế nào để một del_store cửa hàng deleter?

Ban đầu, sử dụng shared_ptr<int>, tôi nghĩ rằng nó có thể sử dụng std::function<void(int*)>, nhưng tôi có thể cung cấp, như một deleter, bất kỳ loại chức năng nào (hoặc các đối tượng có thể gọi), miễn là tham số đầu tiên là int*.

Làm cách nào để shared_ptr thực hiện việc này?

Tôi xin lỗi nếu đây là câu hỏi ngớ ngẩn, tôi mới tham gia C++, hãy tha thứ cho tôi!

Chỉnh sửa: Câu hỏi đặt ra là: làm cách nào tôi có thể làm điều gì đó như vậy? Tôi nên sử dụng cái gì? Ví dụ nào? Hoặc nó là một chủ đề rất tiên tiến?

+1

Bạn có muốn biết về trình biên dịch và thư viện cụ thể của bạn? (Nếu có, hãy cho chúng tôi biết bạn đang sử dụng cái gì) Hoặc C++ Standard nói gì về tất cả các triển khai phù hợp? –

+0

Tôi sẽ biết làm thế nào tôi có thể làm một cái gì đó như thế. Tôi sẽ chỉnh sửa tin nhắn. – Toccio

+1

@Toccio: Hành vi đó được bật bởi các mẫu. Đó là một chủ đề nâng cao. Kudos cho câu hỏi, đó là hợp lý và cũng đặt. – Jon

Trả lời

7

Dấu phân cách, cũng như trình phân bổ, được xóa. Con trỏ được chia sẻ quản lý một đối tượng điều khiển được phân bổ động, riêng tư, được truy cập thông qua một cơ sở đa hình và lưu trữ tất cả trạng thái và chức năng kiểu cụ thể.

Việc triển khai std::function sử dụng các ý tưởng tương tự vì nó cũng là lớp trình quản lý động loại xóa, nhưng cả hai đều được triển khai hoàn toàn riêng biệt.

Kết quả là cả hai lớp tương đối "đắt" và chỉ nên được sử dụng khi chúng thực sự cần thiết. Nếu không, các giải pháp phi linh hoạt rẻ hơn, không đa hình thường thích hợp hơn.

4

Tôi có thể cung cấp, như một deleter, bất kỳ loại chức năng nào (hoặc các đối tượng có thể gọi), miễn là tham số đầu tiên là int*.

Không, không thực sự. Các nhà xây dựng std::shared_ptr có hợp đồng sau đây, được tìm thấy trong phần 20.8.2.2.1 ([util.smartptr.shared.const]):

template<class Y, class D> shared_ptr(Y* p, D d); 
template<class Y, class D, class A> shared_ptr(Y* p, D d, A a); 
template <class D> shared_ptr(nullptr_t p, D d); 
template <class D, class A> shared_ptr(nullptr_t p, D d, A a); 

Yêu cầu: p sẽ chuyển đổi thành T*. D sẽ là CopyConstructible. Trình tạo bản sao và hàm hủy của D sẽ không ném ngoại lệ. Biểu thức d(p) phải được tạo thành tốt, phải có hành vi được xác định rõ và không được ném ngoại lệ. A sẽ là người cấp phát (17.6.3.5). Các nhà xây dựng bản sao và destructor của A sẽ không ném ngoại lệ.

Hiệu ứng: Xây dựng đối tượng shared_ptr sở hữu đối tượng p và deleter d. Các nhà thầu thứ hai và thứ tư sẽ sử dụng một bản sao của a để cấp phát bộ nhớ để sử dụng nội bộ.

Điều kiện sau: use_count() == 1 && get() == p.

Ném: bad_alloc hoặc ngoại lệ được triển khai khi tài nguyên không phải là bộ nhớ không thể nhận được.

An toàn ngoại lệ: Nếu ngoại lệ bị ném, hãy gọi d(p).

Yêu cầu này mạnh hơn rất nhiều so với tham số đầu tiên của dấu phân cách phải là loại phù hợp.Nó phải là tham số duy nhất (không có đối số mặc định), chẳng hạn như d(p) là hợp pháp. Điều này hơi linh hoạt hơn std::function<void (int*)>, bởi vì kiểu trả về có thể là bất kỳ thứ gì, nhưng nó cũng bị ràng buộc nhiều hơn đối với các bảo đảm ngoại lệ.

Nếu trình biên dịch của bạn không bắt được bạn khi bạn cung cấp một deleter với nhiều tham số bắt buộc, việc triển khai thư viện chuẩn đang làm điều gì đó không đúng.

Theo như cách triển khai, hãy tận dụng thực tế là nó phải là CopyConstructible. Ví dụ, lambda sau nên làm việc khá độc đáo, và có thể chuyển nhượng để std::function<void(void)> (bảo lãnh CopyConstructible đảm bảo rằng chụp bởi công trình giá trị):

[d, p] { d(p); } 
+0

@hvd: Tôi đã nói "phải là tham số duy nhất không có đối số mặc định". Trong ví dụ của bạn, nó là. –

+0

Ah, cảm ơn vì đã dọn dẹp, tôi đã đọc sai câu trả lời của bạn. – hvd

+1

"Nếu trình biên dịch của bạn không bắt bạn khi bạn cung cấp một deleter với nhiều tham số cần thiết, nó làm một cái gì đó khá sai." Không cần thiết. Vi phạm điều khoản * Yêu cầu * gây ra UB. Trình biên dịch là không cần thiết để chẩn đoán nó. –

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