2012-07-02 29 views
12

Tôi cố gắng viết lớp nàyhành vi kỳ lạ cho unique_pointer trong Visual Studio 2010

#include <memory> 

class ContainerUnique 
{ 
public: 

    ContainerUnique(void); 
    ~ContainerUnique(void); 

private: 
    std::unique_ptr<UniqueElement> u; 
}; 

đâu UniqueElement là một lớp POD được xác định ở nơi khác. Bây giờ tôi xác định phần thân của hàm tạo như sau:

ContainerUnique::ContainerUnique(void) 
{ 
    auto tmp = new UniqueElement(1); 

    this->u(tmp); // u is a unique_ptr<UniqueElement>. Should this call compile? 
} 

Và nó không tuân thủ ngoại lệ. Chạy chương trình tôi thấy rằng sau khi hàm tạo của ContainerUnique đã được gọi, u chứa một con trỏ rỗng.

Đây có phải là hành vi dự định không? Và tôi đang gọi phương thức unique_ptr nào?

+3

Không chắc chắn về các sự cố bạn đang gặp phải. Nhưng tránh chúng bằng cách khởi tạo biến thành viên u trong danh sách initialaztrion của hàm tạo. –

+0

Vâng, đó là giải pháp tôi đã sử dụng trong mã thực sự của mình, nhưng tôi vẫn không chắc chắn về những gì đang xảy ra trong ví dụ. –

+0

Thử in loại biến số tự động của bạn. Không chắc chắn nếu typeid hoạt động. Một khi bạn biết loại phần còn lại nên dễ dàng. –

Trả lời

19

This is a known problem with VS2010's unique_ptr.công khai thừa hưởng từ deleter của nó nếu nó trống rỗng như một tối ưu hóa (trống tối ưu hóa cơ sở). Nhược điểm của thừa kế công khai là tất cả các thành viên của deleter cũng trở thành thành viên có sẵn của unique_ptr, trong trường hợp này là operator()(T*) để xóa con trỏ.

Lỗi được sửa trong thư viện của VS2012, nơi di sản được thay đổi thành riêng tư.

+1

ah, bạn đánh tôi với nó. Tốt tìm. – stijn

2

Nó nên được thực hiện như

ContainerUnique::ContainerUnique(void):u(new UniqueElement(1)) { 
} 
+1

Đây là cách tôi giải quyết vấn đề trong mã sản xuất của tôi, nhưng tôi vẫn không chắc chắn về những gì đang xảy ra trong ví dụ. –

8

Bạn đang gọi default_delete<UniqueElement>::operator() (UniqueElement* ptr), vì uniqe_ptr xuất phát từ nó (để hưởng lợi từ tối ưu hóa lớp cơ sở trống) và nó xóa ptr. Nó không phải là hành vi chính xác dành cho bạn, mặc dù tôi không nghĩ tiêu chuẩn cấm nó.