shared_ptr 和 unique_ptr 构造函数

Posted

技术标签:

【中文标题】shared_ptr 和 unique_ptr 构造函数【英文标题】:shared_ptr and unique_ptr constructor 【发布时间】:2021-08-28 21:08:07 【问题描述】:

当我使用智能指针时,我总是需要用工厂函数来构造它,例如std::make_shared<T>std::make_unique<T>,我不使用带有指针的构造函数,因为我试图避免 new 的任何用法/外观。但我的问题是,为什么 C++ 标准没有包含一个将参数列表转发到 T 类型的构造函数?喜欢而不是shared_ptr<T> make_shared(Args&&...),我们可以有以下内容:

shared_ptr<T>::shared_ptr(Args&&...) ...
unique_ptr<T>::unique_ptr(Args&&...) ...

【问题讨论】:

可能很难(但并非难以置信)得到一个非意见的答案。我首先想到的是如果T 可以从T* 构造出来呢?这个案子的模棱两可值得吗?这可能是一个见仁见智的问题,除非有人能从标准委员会那里找到讨论这一点的说明。 关于“我尽量避免使用new”,为什么?我知道赤裸裸的new 电话通常是个坏主意,但并非在所有情况下都如此。如果在智能指针构造函数中使用该关键字肯定可以吗? 一个问题是,在这种情况下,您可能不希望使用默认构造函数来构造对象,而是使用nullptr 【参考方案1】:

基本上是为了避免歧义和混淆。

之所以会产生歧义,是因为std::shared_ptr 有超过 10 个构造函数重载,std::unique_ptr 也有六个,其中很多是模板。因此,添加一个旨在将参数转发给托管对象的函数将导致编译器无法选择其含义或无法访问托管对象的某些构造函数。

即使以某种方式避免了歧义,也可能会混淆用户。这是因为shared_ptr 构造函数用于构造shared_ptr 对象,而make_shared 用于使对象由shared_ptr 管理。

这些工厂的想法不是要摆脱代码中new 的出现。从 make_shared 获取值的 shared_ptr 管理资源的方式与从构造函数之一获取值的 shared_ptr 不同。摆脱 new 只是令人愉快的副产品,但我们仍然需要那些构造函数(例如用于设置删除器),因此在代码中区分它可以简化阅读。

【讨论】:

从 make_shared 获取值的 shared_ptr 管理资源的方式与从构造函数之一获取值的 shared_ptr 不同 - 你能解释一下你的意思吗?它们有什么不同? make_shared 只为控制块和托管对象分配一次。因此,当 shared_ptr 的计数达到零时,此类 shared_ptr 调用托管对象的析构函数,但必须等待整个内存的释放,直到没有weak_ptr 剩余。接收到管理指针的shared_ptr只分配控制块,当shared_ptr计数为零时调用deleter(注意不是析构函数),当weak_ptr计数为零时释放该控制块。 @fluter 你可能想看看cppreference's list of trade-offs。

以上是关于shared_ptr 和 unique_ptr 构造函数的主要内容,如果未能解决你的问题,请参考以下文章

`std::optional` 比 `std::shared_ptr` 和 `std::unique_ptr` 有啥优势?

shared_ptr 和 unique_ptr

shared_ptr 和 unique_ptr 构造函数

智能指针shread_ptrweak_ptr 和 unique_ptr之一

智能指针shread_ptrweak_ptr 和 unique_ptr之一

面试———智能指针