2013-07-28 29 views
5

Khi tôi tạo ra một unique_ptr với deleter, nó hoạt động:unique_ptr là không nhận được init với mặc định deleter

std::unique_ptr<Animal<Cat>, void(*)(Animal<Cat>*)> ptr(new Animal<Cat>, [](Animal<Cat> *ls) { 
    delete ls; 
}); 

Nhưng, mã này được ném lỗi:

std::unique_ptr<Animal<Cat>, void(*)(Animal<Cat>*)> ptr; 
ptr = std::unique_ptr<Animal<Cat>, void(*)(Animal<Cat>*)>(new Animal<Cat>, [](Animal<Cat> *ls) { 
    delete ls; 
}); 

Lỗi:

/usr/bin/../lib/c++/v1/memory:2561:13: error: static_assert failed "unique_ptr constructed with null function pointer deleter" 
       static_assert(!is_pointer<deleter_type>::value, 
       ^   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
note: in instantiation of member function 'std::__1::unique_ptr<Animal<Cat>, void (*)(Animal<Cat> *)>::unique_ptr' requested here 
      std::unique_ptr<Animal<Cat>, void(*)(Animal<Cat>*)> ptr; 
                   ^

Đây là phiên bản trình biên dịch của tôi:

Apple clang version 4.0 (tags/Apple/clang-421.0.60) (based on LLVM 3.1svn) 
Target: x86_64-apple-darwin12.4.0 
Thread model: posix 

Lớp Động vật và mèo là tầm thường. This is the entire code.

Trả lời

10

Dường như không thể xây dựng mặc định unique_ptr bằng loại con trỏ cho dấu phân cách. Các unique_ptr nhà xây dựng được nêu chi tiết trong §20.7.1.2.1 [unique.ptr.single.ctor] mà nói, trong số những thứ khác:

constexpr unique_ptr() noexcept;

4 Remarks: If this constructor is instantiated with a pointer type or reference type for the template argument D [the deleter type], the program is ill-formed.

Something tương tự như những gì bạn muốn mà là phù hợp với tiêu chuẩn:

unique_ptr<int, void(*)(int*)> ptr{nullptr,[](int*p){delete p;}}; 
// ... 
ptr.reset(new int(42)); 
10

Sau khi đọc câu trả lời của Casey ở trên, tôi đã thay đổi mã của mình để sử dụng Functors cũ thay vì lambda để làm cho nó hoạt động.

Đây là giải pháp của tôi:

struct Deleter { 
    void operator()(Animal<Cat>* ls) { 
     delete ls; 
    } 
}; 

int main() { 
    std::unique_ptr<Animal<Cat>, Deleter> ptr; 
    ptr = std::unique_ptr<Animal<Cat>, Deleter>(new Animal<Cat>); 
    return 0; 
} 
+1

Lý giải cho hành vi này 'unique_ptr' là cố gắng thông báo cho bạn tại thời gian biên dịch rằng một hàm con trỏ-to-null không phải là một deleter tốt. Bạn có thể ghi đè hành vi này bằng cách gửi một cách rõ ràng trong một dấu phân cách nullptr. Nhưng giải pháp bạn chọn thay thế là tốt hơn. –

+0

@HowardHinnant Nó sẽ kiểm tra nullptr lúc chạy hay nó sẽ cố gọi hàm đó? – user877329

+0

@ user877329: Nếu '~ unique_ptr()' hoặc 'reset()' được gọi và 'get_deleter() (get())' không được định dạng đúng, bạn sẽ nhận được hành vi không xác định. –

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