我最近遇到了以下内存错误,在这里很容易发现,但在更复杂的代码中更难检测到:
class Foo : public IFoo {
const Bar& bar_;
public:
Foo(const Bar& bar) : bar_(bar) {
}
void test() {
// access bar_ here
}
};
int baz() {
IFoo* foo = NULL;
if(whatever) {
Bar bar;
foo = new Foo(bar);
}
else {
// create other foo's
}
foo->test(); // segmentation fault
}
错误是Bar
立即超出范围,被销毁然后在foo->test()
. 一种解决方案是Bar
在堆上创建,使用Bar* bar = new Bar()
. 但是,我不喜欢这样做,因为我必须将Bar* bar
指针保持在顶层,这样我才能delete
在最后访问它,即使Bar
是特定于该特定代码块的东西if(whatever){}
。
另一个解决方案是boost::shared_ptr<Bar>
,但我不能只写这个:
if(whatever) {
boost::shared_ptr<Bar> bar(new Bar());
foo = new Foo(*bar);
}
因为shared_ptr
也立即超出范围,破坏了包含的对象。
所以简而言之,为了摆脱这个问题,我必须在shared_ptr
任何地方使用,inFoo
作为成员变量,inFoo
的构造函数等。为了消除这些问题,我所有的 API 等都必须使用shared_ptr
,这很友好丑陋的。但是,这样做是正确的吗?到目前为止,我有时使用它来创建引用计数对象,但我的 API 保持干净shared_ptr
。你如何处理这个问题,一旦你使用,shared_ptr
你必须在任何地方使用它?
(另外,如果你使用这些引用计数的指针,你必须开始担心你是否真的想要shared_ptr
或者更确切地说weak_ptr
等等)
而且,我将使用什么来等效于Foo(const Bar& bar)
?Foo(const shared_ptr<const Bar> bar)
?
当然,另一种选择是在自己的Bar
对象和其他对象中添加引用计数,使用pimpl
自己的计数器,但作为一般规则,这太乏味了。