【发布时间】:2010-12-10 16:08:45
【问题描述】:
boost::shared_ptr 真的很困扰我。当然,我理解这种东西的用途,但我希望我可以使用shared_ptr<A> as 和A*。考虑以下代码
class A
{
public:
A() {}
A(int x) {mX = x;}
virtual void setX(int x) {mX = x;}
virtual int getX() const {return mX;}
private:
int mX;
};
class HelpfulContainer
{
public:
//Don't worry, I'll manager the memory from here.
void eventHorizon(A*& a)
{
cout << "It's too late to save it now!" << endl;
delete a;
a = NULL;
}
};
int main()
{
HelpfulContainer helpfulContainer;
A* a1 = new A(1);
A* a2 = new A(*a1);
cout << "*a1 = " << *a1 << endl;
cout << "*a2 = " << *a2 << endl;
a2->setX(2);
cout << "*a1 = " << *a1 << endl;
cout << "*a2 = " << *a2 << endl;
cout << "Demonstrated here a2 is not connected to a1." << endl;
//hey, I wonder what this event horizon function is.
helpfulContainer.eventHorizon(a1);
cout << "*a1 = " << *a1 << endl;//Bad things happen when running this line.
}
创建 HelpfulContainer 的人并没有考虑其他人想要保留指向 A 对象的指针。我们不能给 HelpfulClass boost::shared_ptr 对象。但我们可以做的一件事是使用 pimlp 习语创建一个 SharedA,它本身就是一个 A:
class SharedA : public A
{
public:
SharedA(A* a) : mImpl(a){}
virtual void setX(int x) {mImpl->setX(x);}
virtual int getX() const {return mImpl->getX();}
private:
boost::shared_ptr<A> mImpl;
};
然后主函数可以是这样的:
int main()
{
HelpfulContainer helpfulContainer;
A* sa1 = new SharedA(new A(1));
A* sa2 = new SharedA(sa1);
cout << "*sa1 = " << *sa1 << endl;
cout << "*sa2 = " << *sa2 << endl;
sa2->setX(2);
cout << "*sa1 = " << *sa1 << endl;
cout << "*sa2 = " << *sa2 << endl;
cout << "this demonstrates that sa2 is a shared version of sa1" << endl;
helpfulContainer.eventHorizon(sa1);
sa2->setX(3);
//cout << "*sa1 = " << *sa1 << endl;//Bad things would happen here
cout << "*sa2 = " << *sa2 << endl;
//but this line indicates that the originally created A is still safe and intact.
//only when we call sa2 goes out of scope will the A be deleted.
}
所以,我的问题是这样的: 上述模式是一个好的模式,还是有什么我还没有考虑。我当前的项目继承了一个类似上面的HelpfulContainer 类,它删除了我需要的指针,但我仍然需要 HelpfulContainer 中存在的数据结构。
更新:question 是一个后续问题。
【问题讨论】:
-
如果 HelpfulContainer 想要获得指针的所有权,它应该使用正确的语义来这样做。接口
eventHorizon的名字很糟糕,因为它没有解释正在发生的事情,并且它所采用的参数应该表明所有权正在转移(比如 std::auto_ptr 或其新的替代品 std::unique_ptr)。这两个都表明 HelpfullContainer 对象正在获取该对象的所有权,因此在调用后它将不再有效。所以你证明了一点,在 C++ 代码中,不了解语言语义的人可能会写得很糟糕。
标签: c++ shared-ptr smart-pointers pimpl-idiom