在“ C ++ Primer,第5版”中,据说a的删除器的类型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.
如果in中的deleterUniquePtr
是指向函数的指针,但该指针是nullptr
,则del(p)
未定义。
请帮助我理解这一段。我已经实施了我的课程,shared_ptr
并且unique_ptr
仅作为练习。
我认为,SharedPtr中删除器的类型在编译时(
void(*)(T*)
)是已知的,但其值不是。
您的SharedPtr确实如此。
std :: shared_ptr并非如此。
另一方面,在编译时也确实知道UniquePtr中删除器的类型,但再次可能不知道该值。
当使用实例化UniquePtr时std::function<void(T*)>
,您只会在编译时知道该类型,而不能知道它包装的函数对象的类型。
std :: unique_ptr默认不使用std :: function删除器。
如果UniquePtr中的删除程序是一个函数的指针,但该指针为nullptr,则未定义del(p)。
这是真的。不要那样做
请帮助我理解这一段。
仅仅因为唯一的指针可以在编译时知道一个删除器,并不意味着它必须具有这样的删除器。函数包装器不是函数指针,也不是编译时删除器,因为它们具有运行时状态。
例如,使用无状态删除器std::default_delete<T>
(或引号中提到的DebugDelete大概也是无状态的)来获得编译时的好处。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句