代码之家  ›  专栏  ›  技术社区  ›  bitmask

我能检查一下“从这里共享”通话是否安全吗?

  •  0
  • bitmask  · 技术社区  · 7 年前

    打电话的时候 shared_from_this 从继承自 enable_shared_from_this ,非常糟糕的事情(TM)可能会发生,如果 this 目前不是由 shared_ptr 对象(通常是应用程序崩溃)。在C++14(而不是17)中是否可以检查它是否安全?

    编辑:不使用异常或try/catch。

    3 回复  |  直到 7 年前
        1
  •  1
  •   Gem Taylor    7 年前

    这是一个实现细节,但你能对内部好友声明做些不好的事情吗:

    template<typename _Tp1>
    friend void
    __enable_shared_from_this_helper(const __shared_count<>& __pn,
                     const enable_shared_from_this* __pe,
                     const _Tp1* __px) noexcept
    

    使用_Tp1作为弱_ptr<>*,这将返回弱指针[实际上并不完全是因为_px是常量指针,所以需要额外的间接操作来丢失常量,或者如果你还是脏的,就把它扔掉!] 。将其全部封装在一个类中,然后从中派生,而不是从中启用共享:

    #if >= C++17
    using enable_shared_from_this_c17 = enable_shared_from_this;
    #else
    
    template<typename _Tp>
    enable_shared_from_this_c17: public enable_shared_from_this<_Tp>
    {
    
      weak_ptr<_Tp> weak_from_this()
      {
        weak_ptr<_Tp> rv; auto rv2 = &rv;
        __enable_shared_from_this_helper(*(const __shared_count<>*)nullptr, this, &rv2);
        return rv;
      }
    }
    #endif
    

    现在,我们在c++14中实现了来自_this()的弱_。是的,这是一个讨厌的棍棒,但它只是直到你升级到17。

    或者,抓住例外!

    第三种选择——添加一个实例化模板包装器,在包装器中为enable_shared_from_this设置“constructed”,该包装器将shared_from_this()包装,以便在设置constructed标志之前失败。

    enable_shared_from_this
        safe_shared_from_this
            your interfaces
                your_implementation
                    constructed<your_implementation>
    

    当然,如果使用该类时没有立即分配给共享的_ptr,这是不完美的。

        2
  •  0
  •   Mateusz Drost    7 年前

    如果 this 不是由 shared_ptr 那你什么都做不了。参考文献: It is permitted to call shared_from_this only on a previously shared object, i.e. on an object managed by std::shared_ptr. 下面是一个例子:

    #include <memory>
    
    class MyClass;
    
    std::shared_ptr<MyClass> global;
    
    void resetGlobal()
    {
        global = std::make_shared<MyClass>();
    }
    
    class MyClass : public std::enable_shared_from_this<MyClass>
    {
    public:
        void use()
        {
            resetGlobal();
            shared_from_this();
        }
    };
    
    int main()
    {
        global = std::make_shared<MyClass>();
        global->use();
        return 0;
    }
    

    在开始 use 方法 shared_from_this 应该可以(除了在没有互斥锁的多线程环境中),但是在调用任何可以改变 共享ptr 在其他地方你不能确定。打完电话 resetGlobal 作用 只会被破坏,任何对它的访问都是未定义的行为,因此可能会导致分割错误。

    确保通过整个方法调用 分享了这个 是有效的是暂时的 共享ptr 在通话开始时:

    void use()
    {
        std::shared_ptr<MyClass> tmp = shared_from_this();
        resetGlobal();
        shared_from_this();
    }
    

    {
        std::shared_ptr<MyClass> tmp = global;
        global->use();
    }
    
        3
  •  0
  •   joeybladb    6 年前

    如果程序中的任何其他对象可以访问对象的原始 this 指针,那么您正在使用 shared_ptr 完全错了。

    任何指向外部对象的指针都必须用 shared_ptr<YourObject> 值实例,没有例外。

    推荐文章