【问题标题】:A non-shared smart pointer with incomplete types具有不完整类型的非共享智能指针
【发布时间】:2012-01-30 09:26:18
【问题描述】:

是否有一个标准指针类(或 Boost),它是一个适用于不完整类型的非共享指针?我翻阅了 C++11 标准和 boost 库,但没有找到,但它似乎是一种非常有用的类型。

例如,我希望能够使用智能指针创建不透明类型。

  class A;
  wrap_ptr<A> some_func();
  void other_func( A const & );

A 是一种不透明类型,可用于多种功能。上述接口的用户只有一个不完整的 A 定义,但应该能够删除/重置指针。我知道上面可以用shared_ptr 完成,但是在这个特定的代码中我不希望有开销。 unique_ptr 具有正确的所有权语义,但不能使用不完整的类型。理论上,包装器应该只需要拥有指向删除器的指针的开销。

C++11 或 boost 库中是否有这种类型?

注意:我知道我可以轻松构建这种类型,但如果可能的话,我更喜欢标准类型。看起来它应该是一个基本的智能指针类型。


更新unique_ptr 似乎不是一个好的选择。首先,语法开销将被抵消。其次,我不相信它可以安全地与自定义删除器一起使用。我会检查一下它是如何工作的。

【问题讨论】:

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


    【解决方案1】:

    要清楚 unique_ptr :它确实适用于不完整的类型,但如果你在这样的类的标题中使用它:

    #include <memory>
    
    class A;
    
    class B
    {
    
    std::unique_ptr<A> m_a;
    
    };
    

    由于缺少删除器实现,它不会链接。 有一个简单的解决方法:只需在 cpp 中定义宿主类的析构函数,即使它是空的或者应该是默认的!

    // B.hpp
    #include <memory>
    
    class A;
    
    class B
    {
    public:
    
        B();
        ~B();
    
    private:
    
    std::unique_ptr<A> m_a;
    
    };
    
    // B.cpp
    
    B::B(){} // or =default; (if you have a compiler providing it)
    B::~B(){} // or =default; (if you have a compiler providing it)
    

    另外,请阅读我的问题的答案:Is std::unique_ptr<T> required to know the full definition of T?

    也许看看 Herb Sutter 建议如何实现 pimpl idiom(暗示 unique_ptr 中的不完整类型):http://herbsutter.com/gotw/_100/

    【讨论】:

    • 这不是我想要的用途。我想在函数的返回值中使用指针,在调用者永远看不到完整类型的地方。
    【解决方案2】:

    实际上,unique_ptr 可以处理不完整的类型,只要您指定自定义删除器即可。

    然而,与shared_ptr相反,这实际上会影响其类型,因为自定义删除器是静态精确的(作为第二个模板参数)。

    【讨论】:

    • 虽然在技术上是正确的,但直接使用它在语法上是不友好的。你不能简单地做ptr_type( new T ),但是,假设你得到了正确的模板typedef,你必须做ptr_type( new T, T::~T )
    • 实际上,仔细观察unique_ptr 不能使用带状态的自定义删除器。 reset 函数不允许指定删除器,只有构造函数可以,因此 unique_ptr 的自定义删除方面被部分破坏。
    • 不需要自定义deleter,只需要在unique_ptr的析构函数被调用时类型是完整的,也就是说你可以在持有的类完成后定义析构函数。
    • @Xeo:首先,析构函数对于移动赋值和reset也是必须的(我想不出任何其他方法)。其次,OP 不是在谈论延迟定义,而是在谈论不透明类型。在 C 语言中,这是客户端永远不会看到定义的典型情况。
    • @edA-qamort-ora-y:“实际上,仔细观察 unique_ptr 不能使用带有状态的自定义删除器。”不对。该标准明确表示它将保存删除器的副本(20.7.1.2.1,p12)。仅仅因为reset 不能重置删除器的值并不意味着该值未被使用。 reset 不使用删除器,因为删除器可以通过引用存储在 unique_ptrs 中。因此不能保证您能够更换它们。
    【解决方案3】:

    std::unique_ptr 可以处理这种情况,但不能使用默认删除器。你需要编写一个可以处理不完整类型的删除器,然后使用std::unique_ptr&lt;A,MyDeleter&gt;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-02
      • 1970-01-01
      • 2012-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多