在《C++ Primer, 5th Edition》中提到,
因此,我制作了以下示例:
如果UniquePtr中的删除器是函数指针,但该指针为nullptr,则del(p)的行为未定义。
请帮我理解这段话。我已经实现了我的shared_ptr和unique_ptr,仅仅是为了练习。
shared_ptr
的删除器类型直到运行时才知道,因为该删除器并没有直接作为成员存储,而是作为一个指针来指向删除器。而在 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,仅仅是为了练习。
std::unique_ptr<int, std::function<void(int*)>> upi(new int{7}, [](int* p ){delete p;});
,它是否与std::shared_ptr
的运行时开销相同? - Maestrostd::function
和std::shared_ptr
的删除器中。 - Daniel Langr