簡體   English   中英

為什么unique_ptr不會阻止自定義刪除器的切片?

[英]Why unique_ptr doesn't prevent slicing of custom deleter?

具有custom deleterstd::unique_ptr的行為基於custom deleter器的靜態類型 沒有多態性,沒有基於在運行時傳遞的實際刪除器的運行時行為,因為提供的派生刪除器被切片到聲明的刪除器的靜態類型。

(它以這種方式設計,允許使用default deleter的unique_ptr的大小或custom deleter without any data members大小,以使其具有與原始指針相同的大小)。

custom deleterunique_ptr靜態行為:

class A {};

struct BaseDeleter {
    virtual void operator()(A* p) const {
        std::cout << "in BaseDeleter" << std::endl; 
        delete p;
    }
};

struct DerivedDeleter: BaseDeleter {
    void operator()(A* p) const override {
        std::cout << "in DerivedDeleter" << std::endl; 
        delete p;
    }
};

int main() {
    auto unique_var = std::unique_ptr<A, BaseDeleter>(new A);
    unique_var = std::unique_ptr<A, DerivedDeleter>(new A);
}

輸出:

in BaseDeleter
in BaseDeleter

這與std::shared_ptr相反,后者以不同方式保存自定義刪除器並允許動態行為:

shared_ptrcustom deleter動態行為:

int main() {
    auto shared_var = std::shared_ptr<A>(new A, BaseDeleter{});
    shared_var = std::shared_ptr<A>(new A, DerivedDeleter{});
}

輸出:

in BaseDeleter
in DerivedDeleter

代碼: https//coliru.stacked-crooked.com/a/54a8d2fc3c95d4c1


使用不同的custom deleter分配std::unique_ptr的行為實際上是切片

為什么unique_ptr不會阻止自定義刪除器的切片?

如果指定的unique_ptr具有不同的custom deleter ,為什么語言不會阻止std::unique_ptr的賦值,以避免切片?


這似乎是可能的,如下所示。

阻止unique_ptr切割custom deleter

template<typename TYPE, typename Deleter>
struct my_unique_ptr : std::unique_ptr<TYPE, Deleter> {
    using BASE = std::unique_ptr<TYPE, Deleter>;
    using std::unique_ptr<TYPE, Deleter>::unique_ptr;
    auto& operator=(std::nullptr_t) noexcept {
        return BASE::operator=(nullptr);
    }
    template<typename T, typename OtherDeleter,
      std::enable_if_t<!std::is_same<OtherDeleter, Deleter>::value>* dummy = nullptr>
    auto& operator=(std::unique_ptr<T, OtherDeleter>&& other) = delete;
};

代碼: http//coliru.stacked-crooked.com/a/089cd4c7303ad63e

struct B {
  virtual ~B() = default;
};

struct D : B {};

std::unique_ptr<B> b;
b = std::make_unique<D>();

這里我們有一個經典的用例。 是的,刪除器被切片,但刪除仍然很明確。 你的提議會干擾這一點。 並且可能很難可靠地修改為不干擾。

可以隨時指定一個自定義刪除器,如std::function<void(void*)>以通過類型擦除獲得多態性。 當然,它有開銷,但這是選擇。

默認情況下, unique_ptr針對更常見的用例進行了優化,不常見的用例需要通過請求進行開銷。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM