2010-09-17 41 views
1

我确实收到了一个来自库调用的shared_ptr,并将它和一些资源传回库中。资源只能被删除时的shared_ptr删除其指针:释放boost :: shared_ptr上的资源

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

Library.appendWriter(writer); 

图书馆希望我来管理出*但是当它是安全的话,也不会告诉。本质上,我想要out被删除,如果writer被释放。

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

+1

对我来说,就像createWriter()API定义的契约一样,应该指定谁拥有输入流*,并且暗示它如何以及何时被释放。要么图书馆释放它,要么你必须。我没有看到它封装在一个shared_ptr帮助,除非这是如何定义createWriter()。 – 2010-09-17 17:24:03

+0

他们没有指定它,但从看他们的代码,我看到他们希望我拥有它。不幸的是,当他们不再使用它时,他们不告诉我。这就是为什么它认为等待shared_ptr发布可能是一个可行的解决方案。 – 2010-09-17 17:31:22

+1

除非API采用shared_ptr ,否则您已经回到了原点。一旦交给图书馆后会发生什么?它在库代码中不再被使用时显而易见?如果您可以将最终的使用情况与代码中的API使用情况相关联,则可以确定一个合理的点来假设您可以清理流。 – 2010-09-17 17:52:38

回答

1

我不相信你可以直接用shared_ptr API来做到这一点。

如果Lib :: SomeClass是一个接口/抽象基类,您可能可以使用Decorator。这个想法是定义一个类Lib::SomeClass的子类,包含shared_ptr<Lib::SomeClass>std::ofstream*,其方法都转发给包含的shared_ptr的相应方法。然而,装饰者的析构函数将删除包含的ofstream(或者您可以将其存储在某种RAII容器中,如scoped_ptr)。所以这将是您传递给appendWriter的装饰器实例。这里有一个素描:

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); 
+0

谢谢! '作家'确实是一个界面,所以这种方法很好用! – 2010-09-20 17:21:58

1

你可以尝试在保证寿命比任何参考writer一个范围,在栈上创建的输出流。这取决于你的架构,这是否可能(尽管我会认为在一个好的架构中它应该是)。

如果您有机会与图书馆设计师进行谈判(如您在评论中提及的那样),如果足够,请告诉他/她将参数作为参考。仅当对象的所有权真正共享时才应使用shared_ptr

+0

不幸的是,API设计在这里被歪曲了。堆栈不够长,无法看到正在使用的作者的末尾。 – 2010-09-20 17:22:44

+0

@Christopher Oezbek:那么,一些堆栈帧必须至少和最后一个指针一样长。但我承认,如果把输出流放到某个不属于这个位置的地方,那可能会更糟糕。 – 2010-09-20 19:10:14