C++ boost::shared_ptr终结时释放资源

C++ boost::shared_ptr终结时释放资源,c++,boost,shared-ptr,C++,Boost,Shared Ptr,我确实从库调用中接收到一个共享的\u ptr,并将它和一些资源传递回库中。只有当共享\u ptr删除其指针时,才能删除资源: std::ofstream* out = new std::ofstream(); ... shared_ptr<Lib::SomeClass> writer = Library.createWriter(out); Library.appendWriter(writer); std::ofstream*out=新std::ofstream(); ...

我确实从库调用中接收到一个共享的\u ptr,并将它和一些资源传递回库中。只有当共享\u ptr删除其指针时,才能删除资源:

std::ofstream* out = new std::ofstream(); 
...
shared_ptr<Lib::SomeClass> writer = Library.createWriter(out);

Library.appendWriter(writer);
std::ofstream*out=新std::ofstream();
...
shared_ptr writer=Library.createWriter(out);
图书馆。附录作者(writer);
图书馆希望我管理好,但没有告诉我什么时候这样做是安全的。本质上,如果发布了
writer
,我希望将
out
删除


使用boost的deleter工具可以实现这一点吗?想法?

我不相信您可以通过共享的ptr API直接实现这一点

如果Lib::SomeClass是接口/抽象基类,则可以使用。其思想是定义一个类,该类的子类为
Lib::SomeClass
,包含一个
shared\u ptr
和一个
std::ofstream*
,其方法都转发到所包含的shared\u ptr的相应方法。然而,装饰程序的析构函数将删除包含的
(或者您可以将其存储在某种RAII容器中,如
作用域的\u ptr
)。所以它将是您传递给appendWriter的Decorator的一个实例。这是一张草图:

class SomeClassDecorator : public Lib::SomeClass
{
  public:
    SomeClassDecorator(shared_ptr<Lib::SomeClass> p, std::ofstream* stream)
      : p_(p), stream_(stream)
    {}

    virtual int MethodOfSomeClass(int x) {
        return p_->MethodOfSomeClass(x);
    }

  private:
    shared_ptr<Lib::SomeClass> p_;
    scoped_ptr<std::ofstream> stream_;
};

std::ofstream* out = new std::ofstream(); 
...
shared_ptr<Lib::SomeClass> writer = Library.createWriter(out);
shared_ptr<Lib::SomeClass> wrapper(new SomeClassDecorator(writer, out));

Library.appendWriter(wrapper);
class SomeClassDecorator:public Lib::SomeClass
{
公众:
SomeClassDecorator(共享的\u ptr p,std::of stream*流)
:p_up,stream_u(stream)
{}
某个类的虚拟int方法(int x){
返回某个类(x)的p_->MethodOfSomeClass;
}
私人:
共享的ptr p;
限定范围的ptr流;
};
std::ofstream*out=新std::ofstream();
...
shared_ptr writer=Library.createWriter(out);
共享的ptr包装器(新的SomeClassDecorator(writer,out));
appendWriter(包装器);

您可以尝试在堆栈上创建一个范围内的输出流,该范围保证比对
writer的任何引用活得更长。这取决于您的体系结构,这是否可能(尽管我认为在一个好的体系结构中应该是)


如果你有机会与图书馆设计师进行协商(正如你在评论中提到的),告诉他/她将该论点作为参考,如果这足够的话。
shared\u ptr
仅当对象的所有权真正共享时才应使用。

在我看来,createWriter()API定义的契约应该指定谁拥有Stream*的输入,并暗示如何以及何时发布。要么库释放它,要么你必须释放它。除非createWriter()是这样定义的,否则我不认为将其封装在共享的\u ptr中会有帮助。他们没有指定它,但从查看他们的代码中,我发现他们希望我拥有它。不幸的是,当他们不再使用它时,他们没有告诉我。这就是为什么它认为等待共享的ptr发布可能是一个可行的解决方案。除非API接受共享的ptr,否则你就回到了原点。一旦将ofstream交给图书馆,它会发生什么变化?当它不再使用时,它在库代码中是否很明显?如果您可以将流的最终使用情况与代码中的API使用情况相关联,则可以确定一个合理的点,在该点上可以假定您可以清理流。附带说明:如果您使用的
驻留在一个单独的模块(.dll/.so)中,那么共享的\u ptr deleter应该是匹配的库调用(
Library.releaseWriter)(writer)
或类似),跨模块边界执行新建/删除是一项非常棘手的工作。谢谢各位!因此我必须与库设计师协商更改其界面(没有releaseWriter或回调)。我真的认为boost有一种方法可以在发布共享\u ptr时得到通知。谢谢!
writer
确实是一个接口,所以这种方法工作得很好!不幸的是,API设计在这里是不正确的。堆栈的寿命不够长,无法看到writer被使用的结束。@Christopher Oezbek:好吧,有些堆栈框架已经损坏了至少和最后一个指针一样长。但我承认,将输出流放在不属于它的地方可能是更糟糕的设计。