【问题标题】:Does resetting std::shared_ptr lead to resetting its deleter?重置 std::shared_ptr 是否会导致重置其删除器?
【发布时间】:2019-12-10 04:23:33
【问题描述】:

也许我误解了c++中智能指针的某些方面,但是在执行这段代码之后:

class cls
{
public:
    class deleter
    {
    public:
        const cls& obj;
        deleter(const cls& c) : obj(c) {}
        void operator()(int* num)
        {
            std::cout << "deleter was called" << std::endl;
            if (num)
            {
                std::cout << "num in deleter: " << *num << std::endl;
                if (*num == *obj.int_ptr)
                {
                    std::cout << "equal " << *num << " = " << *obj.int_ptr << std::endl;
                    delete num;
                }
                else
                    std::cout << "not equal" << std::endl;
            }
        }
    };

std::shared_ptr<int> int_ptr;
cls() : int_ptr(nullptr,deleter(*this)) {}
};

int main()
{
    cls obj;
    obj.int_ptr.reset(new int{15});
    return 0;   
}

输出:

deleter was called

0

我注意到 shared_ptr 中的 reset() 删除了自定义删除器,该删除器在其构造函数中传递给它。相反,unique_ptr 没有表现出这种行为,这对我来说似乎很奇怪。

那么这里发生了什么?

【问题讨论】:

  • 这与 STL 无关。
  • @curiousguy std::shared_ptr API 不是 STL 的一部分?
  • @Spongman 绝对不是! STL(标准模板库)的定义很松散,但它主要涉及容器和迭代器以及使用迭代器的算法,以及专门设计用于与它们一起工作的东西——而不是一般用途的构建块。因此,尽管 STL 领域的边界定义不明确,但std::shared_ptr 没有任何特征可以使其成为 STL 的一部分。

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


【解决方案1】:

std::shared_ptr 将删除器存储在控制块中。因此,您可以切换删除器并将 std::shared_ptr 与各种删除器一起使用,同时与指向相同数据的所有其他 std::shared_ptr 实例共享。

std::unique_ptr 不需要任何类型的东西,并在必要时将删除器存储在其实例中。此外,您还必须将删除器的用法指定为模板参数之一。

基本上,std::shared_ptr 中的删除器是数据的一部分,std::unique_ptr 中的删除器是类的一部分。

【讨论】:

    【解决方案2】:

    当我们分配nullptr 或在std::shared_ptr 上调用reset 时,它会在清理内存后清除指针和getdeleter。 unique_ptr 的处理方式不同。

    以下是库中的函数,它减少 shared_ptr 的计数,如果 reference_count 为零,则继续销毁:

    void _Decref() noexcept { // decrement use count
        if (_MT_DECR(_Uses) == 0) {
            _Destroy();
            _Decwref();
        }
    }
    

    因此,一旦您重置并且引用 _count 为零,那么由于重置,自定义删除器的 shared_ptr 将被删除。

    【讨论】:

    • 现在我明白了。非常感谢!
    【解决方案3】:

    删除器在 std::shared_ptr 中的存储方式与在 std::unique_ptr 中的存储方式不同。 std::unique_ptr 使用空基优化 (EBO) 来存储删除器,这意味着 std::unique_ptr 继承了删除器。 std::shared_ptr 不这样做,这就是两者之间删除器 API 不同的原因。

    【讨论】:

      猜你喜欢
      • 2012-12-31
      • 1970-01-01
      • 2015-12-15
      • 2015-07-08
      • 2014-07-04
      • 2018-07-18
      • 2016-01-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多