【问题标题】:shared_ptr and slicingshared_ptr 和切片
【发布时间】:2010-07-22 04:19:50
【问题描述】:

曾经与我共事的人说 shared_ptr 是不安全的,并且在从派生类转换为基类时会切片(即向上转换)。例如,如果有 2 个类 A 和 B,其中 B 派生自 A,则

shared_ptr<A> a(new B)

会切片。我指给他http://www.boost.org/doc/libs/1_43_0/libs/smart_ptr/shared_ptr.htm 它说的地方

只要T* 可以隐式转换为U*shared_ptr&lt;T&gt; 就可以隐式转换为shared_ptr&lt;U&gt;

暗示在这些情况下使用它是安全的,但他似乎不这么认为。

【问题讨论】:

    标签: c++ shared-ptr


    【解决方案1】:

    有人错了,object slicing 不适用于指针。指针使用被包裹在 shared_ptr 中并没有改变这一点 - 它在这里没有做任何特别的魔法,它使用传递给其构造函数的值初始化一个内部指针。

    简化它可以看起来例如出于这个问题的目的,像这样:

    template<class T> struct ptr {
        T* t;
        ptr(T* t) : t(t) {}
        // ...
    };
    

    您丢失了B 的静态类型信息,是的,但指向的对象没有任何变化。

    【讨论】:

      【解决方案2】:

      对象切片确实不适用于指针

      指针是 POD(仅作记录:shared_ptrs 不是)。

      问题引用:

      只要 T* 可以隐式转换为 U*,shared_ptr 就可以隐式转换为 shared_ptr。

      这是关于从一种类型转换为另一种类型,这与向上转换不同。 shared_ptr&lt;A&gt;shared_ptr&lt;B&gt; 之间没有继承关系,无论 A 是否派生自 B 或反之亦然。这就是shared_ptr 对象本身不切片的原因。

      对象切片不是问题

      考虑一个没有虚析构函数的类层次结构 A、B。

      std::shared_ptr<A> a(new B);
      auto a = std::make_shared<B>();
      

      将捕获 B 的释放器,然后在需要时调用 B 的析构函数

      std::shared_ptr<A> a((A*)(new B));
      

      不会做这样的事情,并且会在指向的对象中导致切片问题。

      指针使用被封装在智能指针中这一事实不会改变任何事情

      例如,使用unique_ptr 有不同的行为:

      std::unique_ptr<A> a(new B);
      std::unique_ptr<A> a((A*)(new B));
      

      都会出现切片问题,而

      auto a = std::make_unique<B>();
      

      不会。

      使用普通指针也无济于事:

      A* a = new B{};
      delete a;
      

      是灾难的根源。

      提供示例代码here

      【讨论】:

      • 您首先声明原始指针不能切片,然后以原始指针切片的示例结束...我错过了什么吗?
      • 切片的不是指针,而是指向的对象会遇到切片问题。希望这能解决您的疑问;如果不是,我会尝试提出一个例子或其他东西,但我现在想不出任何东西。我没有找到更好的表达方式,但如果您发现答案的任何部分有更好的措辞,请提出建议。
      猜你喜欢
      • 2019-03-28
      • 2018-06-05
      • 2012-11-10
      • 2016-03-22
      • 2021-01-15
      • 2011-09-13
      • 1970-01-01
      • 2014-07-25
      • 2013-06-12
      相关资源
      最近更新 更多