【问题标题】:about the type of raw pointer inside unique_ptr关于 unique_ptr 中原始指针的类型
【发布时间】:2015-05-02 16:37:06
【问题描述】:

我阅读了《C++ 标准库第二版》一书,发现以下部分:

namespace std {
template <typename T, typename D>
class unique_ptr<T[], D>
{
public:
typedef ... pointer; // may be D::pointer
typedef T element_type;
typedef D deleter_type;
...
};
}

元素类型 T 可能是 void,因此唯一指针拥有一个未指定的对象 类型,就像 void* 一样。另请注意,定义了类型指针,不一定要定义 作为 T*。如果删除器 D 有一个指针 typedef,则将使用此类型。在这种情况下, 模板参数 T 仅具有类型标记的效果,因为没有成员作为 依赖于 T 的类 unique_ptr;一切都取决于指针。 优点是 因此,unique_ptr 可以保存其他智能指针。

读完本节后,我仍然无法理解“一切都取决于指针”的目的。有人可以提供一些示例吗?谢谢。

【问题讨论】:

  • 你不明白什么?为什么 API 是根据 typedef 而不是T* 定义的? ...因为它允许根据其他类型定义 API,所以更加灵活。

标签: c++ c++11 unique-ptr


【解决方案1】:

LWG issue 673pointer 添加到 unique_ptr 规范中。它包含以下动机要点:

  • 已努力在共享内存上下文中更好地支持容器和智能指针。在这种情况下的主要障碍之一 支持不是假设指针类型实际上是T*。这 可以通过删除器轻松完成unique_ptr 定义指针类型:D::pointer。此外这种类型可以 如果删除者D 选择不这样做,很容易默认为T* 定义一个指针类型(这里的示例实现[断开的链接])。这 更改没有运行时开销。它没有接口开销 自定义 delter 类型的作者。它只是允许(但不要求) 自定义删除器类型的作者为 unique_ptr 的存储类型,如果他们发现这样的功能有用的话。 std::default_delete 是默认删除器的示例 指向T* 只需忽略此问题而不包括 pointer typedef

请参阅boost::offset_ptr 以获取可以引用共享内存的示例智能指针。

【讨论】:

  • 或者,假设您的 x86_64 代码使用了很好的宽算术运算和额外的寄存器,但是从进程范围的 32 位堆执行分配(因为 4GB 对于特定问题来说已经足够了)。然后std::unique_ptrs 可能最终每个只有 4 个字节(在空基类优化消除了删除器的开销之后)。并且这样提高了CPU缓存的效果。
【解决方案2】:

unique_ptr 的设计方式是,如果您没有在声明中提供删除器,由于默认模板参数,它使用 default_deleter(std::default_delete&lt;T&gt;),即“delete”您的指针。它使用SFINAE 在您的删除器类型中查找“指针”的定义。如果您的 unique_ptr 持有另一个 smart_ptr(定义了“指针”),那么在析构函数中,它会调用您持有的 unique_ptr 的删除器。

例子:

class BufferClass
{
public:
    BufferClass()
    {
        // init
    }
    ~BufferClass()
    {
        delete [] buffer;
    }
    int *buffer;
};

// a short declaration for unique_ptr<BufferClass>
typedef unique_ptr<BufferClass> BufferPointer;    

BufferPointer myBuffer(new BufferClass(10)); // myBuffer holds BufferClass.
// when myBuffer goes out of scope, u'll have BufferClass::~BufferClass called.

//let's say you want to store a unique_ptr in another unique_ptr.     
unique_ptr<BufferPointer> myBufferPointerPointer(&myBuffer);
//  so when myBufferPointerPointer goes out of scope, BufferClass::~BufferClass will be called eventually

【讨论】:

    猜你喜欢
    • 2021-10-28
    • 2015-10-01
    • 2022-01-17
    • 2019-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-18
    • 2012-04-12
    相关资源
    最近更新 更多