std::unique_ptr 和自定义删除程序
std::unique_ptr and custom deleters
Scott Meyer的"Effective Modern C++"讨论了std::unique_ptr
与自定义删除器的使用,并指出:
作为函数指针的删除器通常会导致
std::unique_ptr
的大小从一个增长 字对二。对于作为函数对象的删除程序,大小的变化取决于函数对象中存储的状态量。无状态函数对象(例如,来自没有捕获的 lambda 表达式)不会产生大小损失,这意味着当自定义删除器可以作为函数或无捕获 lambda 表达式实现时,lambda 更可取。
举个例子,这个:
auto delInvmt1 = [](Investment* pInvestment) {
makeLogEntry(pInvestment);
delete pInvestment;
};
template<typename... Ts>
std::unique_ptr<Investment, decltype(delInvmt1)>
makeInvestment(Ts&&... args);
比这更好:
void delInvmt2(Investment* pInvestment) {
makeLogEntry(pInvestment);
delete pInvestment;
}
template<typename... Ts>
std::unique_ptr<Investment, void (*)(Investment*)>
makeInvestment(Ts&&... params);
我可以看到在第二种情况下,指向删除器函数的指针需要存储在unique_ptr
中,但是为什么不需要为 lambda 情况存储类似的内容?
正如@milleniumbug所说,std::unique_ptr
使用Empty Base Optimization
。这意味着您可以声明一个没有数据成员的类:
class empty
{
public:
// methods
};
如果另一个类在其中声明了empty
的成员变量,则即使类没有数据成员empty
类的大小也会增加:
class foo
{
public:
int i;
empty em;
};
在这种情况下,foo
的大小将为 8 字节。但是如果你声明foo
从empty
继承,这个继承对foo
的大小没有影响,它的大小将是
class foo : public empty
{
public:
int i;
};
如果你看一下编译器std::unique_ptr
实现,你会看到这个。我使用的是VC++ 2015,在这个编译器结构中std::unique_ptr
如下所示:
template<class _Ty, class _Dx> // = default_delete<_Ty>
class unique_ptr : public _Unique_ptr_base<_Ty, _Dx>
它继承自此类:
template<class _Ty, class _Dx>
class _Unique_ptr_base
{ // stores pointer and deleter
public:
...
_Compressed_pair<_Dx, pointer> _Mypair;
};
在_Unique_ptr_base
中有一个类型为_Compressed_pair
的成员。此类以这种方式声明:
template<class _Ty1, class _Ty2, bool = is_empty<_Ty1>::value && !is_final<_Ty1>::value>
class _Compressed_pair final
: private _Ty1
{ // store a pair of values, deriving from empty first
private:
_Ty2 _Myval2;
实际上,如果第二个模板参数是一个空类,则此类是专用的。在这种情况下,它继承自空的 deleter 类,并声明第一个模板参数的成员变量,该参数std::unique_ptr
指针。
- 共享指针和具有自定义删除程序的唯一指针之间的语法差异背后的任何原因
- 如何使用 C 指针的自定义删除器创建unique_ptr?
- 在地图中使用自定义删除器存储unique_ptr
- 指向重载静态成员的函数指针 - 在unique_ptr中用作自定义删除器
- 在unique_ptr<>中使用自定义删除程序 (curl_formfree())
- 用于unique_ptr的有状态自定义删除程序
- 为什么unique_ptr不能阻止自定义删除程序的切片?
- std::unique_ptr 和自定义删除程序
- 如何使用lambda和函数作为unique_ptr的自定义删除程序
- std::unique_ptr,自定义删除程序和类型更改
- shared_ptr<EVP_PKEY> EVP_PKEY_free作为自定义删除程序会导致堆损坏
- 使用自定义删除程序返回unique_ptr的 nullptr 失败
- 对 Direct3D11 对象上使用 std::shared_ptr 的自定义删除程序
- 为shared_ptr但遇到错误指定自定义删除程序
- unique_ptr、自定义删除程序和零法则
- 带有自定义删除程序错误的 c++ 唯一指针
- 使用外部定义的自定义删除程序在头文件中定义唯一指针
- 类成员唯一指针,具有初始值设定项列表外部的自定义删除程序
- 标准::shared_ptrs的自定义删除程序
- 何时对 std::shared_ptr 使用自定义删除程序