【发布时间】:2020-11-16 21:22:17
【问题描述】:
在《C++ Primer, 5th Edition》中,据说一个shared_ptr的deleter的类型直到运行时才知道,因为deleter不是直接作为成员存储的,而是作为一个可以指向的指针到删除器。 unique_ptr 中删除器的类型在编译时是已知的,因为它是 unique_ptr 本身的一部分。
所以,我做了这个例子:
#include <functional>
template <typename T>
struct SharedPtr
{
void(*pDel_)(T*) = nullptr;
T* ptr_{ new T{} };
~SharedPtr(){ pDel_ ? pDel_(ptr_) : delete ptr_; }
};
template <typename T, typename D = std::function<void(T*)>>
struct UniquePtr
{
D pDel_;
T* ptr_{ nullptr };
UniquePtr(T* p = nullptr, D del = D{}) :
ptr_(p), pDel_(del){}
~UniquePtr(){ pDel_(ptr_); }
};
int main()
{
SharedPtr<int> spi{};
cout << *spi.ptr_ << endl;
UniquePtr<std::string> upd{new std::string("Helo!"),
[](std::string* p){std::cout << "freeing memory...\n"; delete p; }};
}
-
在我看来,
SharedPtr中删除器的类型在编译时 (void(*)(T*)) 是已知的,但值不是。 -
另一方面,
UniquePtr中删除器的类型在编译时也确实是已知的,但值可能不知道。 -
所以书上说:
// del bound at compile time; direct call to the deleter is instantiated
del(p); // no run-time overhead
The type of del is either the default deleter type or a user-supplied type. It doesn’t
matter; either way the code that will be executed is known at compile time. Indeed, if
the deleter is something like our DebugDelete class (§ 16.1.4, p. 672) this call might
even be inlined at compile time.
By binding the deleter at compile time, unique_ptr avoids the run-time cost of an
indirect call to its deleter. By binding the deleter at run time, shared_ptr makes it
easier for users to override the deleter.
如果UniquePtr 中的删除器是指向函数的指针,但该指针是nullptr,则del(p) 未定义。
请帮助我理解这一段。我已经实现了我的shared_ptr 和unique_ptr 只是为了练习。
【问题讨论】:
标签: c++ shared-ptr unique-ptr