【问题标题】:Wrapping a releaseable object into a smart pointer将可释放对象包装成智能指针
【发布时间】:2015-10-14 08:16:15
【问题描述】:

据我所知,智能指针的存在是为了避免内存泄漏等。然而,经常有一些对象也需要释放,但不是freedelete。是否有一些通用的方法可以将此类指针与模板一起使用?

想到一个例子FILE,完成后应该使用fclose。当然,还有其他类型的指针具有自己独特的释放功能。那么我是否必须实现单独的包装器来说明它们各自的发布方法,还是有更好的方法来做到这一点?

可以这样使用的东西:

smart_ptr<FILE, fclose> fl = fopen();
smart_ptr<IStream, T->Release> pFileStream = SHCreateStreamOnFile(...);

【问题讨论】:

  • 是的,标准库中的智能指针接受自定义发布函数。

标签: c++ templates pointers


【解决方案1】:

如果您使用的是unique_ptrshared_ptr,您可以提供您的自定义删除器。 unique_ptr 的删除器作为模板参数传递,并且

Deleter 必须是 FunctionObject 或对 FunctionObject 的左值引用或对函数的左值引用,可使用 unique_ptr&lt;T, Deleter&gt;::pointer 类型的参数调用

对于shated_ptr,删除器应作为构造函数参数提供。

class Foo
{

};

class Deleter
{
public:
    void operator()(Foo *)
    {
        std::cout << "deleter";
    }
};

int main() {
    std::unique_ptr<Foo, Deleter> ptr(new Foo());
    std::shared_ptr<Foo> ptr1(new Foo(),
                             [](Foo*){std::cout << "deleter for shared_ptr";}
                             );
}

不过,您必须小心不要导致内存泄漏。

【讨论】:

  • 但这仍然意味着我必须为每种类型的对象编写一个单独的删除器,对吧?
  • @Devolus,是的,对于需要特殊处理的每种类型的对象。
  • 好的。我希望通过提供方法来使用聪明的模板等来解决这个问题,而不必担心这一点。 :)
【解决方案2】:

shared_ptrunique_ptr 都提供该功能。


对于shared_ptr,构造函数是一个模板:

可以提供一个可选的删除器 d,当没有 shared_ptr 对象拥有该对象时,该删除器稍后用于销毁该对象。默认情况下,类型 Y 的删除表达式用作删除器。

在这种情况下,删除器可以是任何可调用的可复制构造 ,它们会被类型擦除到可调用对象。

对于unique_ptr,删除器的类型是指针本身的类型参数:

template<
    class T,
    class Deleter = std::default_delete<T>
> class unique_ptr;

在这种情况下没有擦除,并且提供给c-tor的删除器或重置实际上与删除器类型匹配。

【讨论】:

    【解决方案3】:

    您可以使用自定义删除器构造shared_ptr(签名#3 here)和unique_ptr(签名#2 here)。

    using T = ...;
    auto deleter = [](T* x) { delete x; };
    
    // different deleter - different unique_ptr type
    // deleter is stored inline
    auto x = std::unique_ptr<T, decltype(deleter)>(new T(...), deleter);
    
    // same shared_ptr<T> type regardless of the deleter type,
    // deleter is stored in the "shared state"
    auto y = std::shared_ptr<T>(new T(...), deleter);
    

    注意,make_shared() 不能用于构造带有自定义删除器的 shared_ptr

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-06-16
      • 2012-09-10
      • 2018-12-02
      • 1970-01-01
      • 1970-01-01
      • 2015-06-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多