boost :: shared_ptr真让我烦恼。当然,我理解这种事情的实用性,但我希望我可以将shared_ptr<A>
用作 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.
}
创建有用的容器的人并没有考虑其他人想要保留指向A对象的指针。我们不能提供有助于类的boost :: shared_ptr对象。但我们能做的一件事就是用pimlp成语来创建一个本身就是A的SharedA:
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
类,它正在删除我需要的指针,但我仍然需要有用的容器中的数据结构。
更新:此question是一个后续问题。
答案 0 :(得分:6)
shared_ptr
的重点是它(及其副本)拥有它指向的对象。如果您想将A
提供给管理其生命周期的容器,那么您根本不应该使用shared_ptr
因为它不符合您的需求; HelpfulContainer
只知道如何成为动态创建对象的唯一所有者,因此您需要为其指定一个不属于任何其他对象的对象。
我认为对于一个关心自己的生命周期的对象来说,通常设计不好(有例外)。如果一个对象可以完成一项工作而其他东西管理它的创建和解决方案通常会更有用,选择最简单的生命周期策略(例如本地/自动变量)。
如果您必须在两个不合作的事物(例如shared_ptr
和HelpfulContainer
)之间共享所有权,那么您将不得不使用某种代理技术。
在这种情况下,它看起来只是HelpfulContainer
对您的情况没有帮助。
答案 1 :(得分:1)
我不确定这对你有什么用。
如果helpfulContainer.eventHorizon()
总是删除其参数,那么为什么不传递(原始)A类的新副本:
helpfulContainer.eventHorizon(new A(sa1));
或者,如果helpfulContainer.eventHorizon()
仅有时删除其参数,则将调用作为
helpfulContainer.eventHorizon(new SharedA(sa1));
在选择不删除的情况下,会泄漏 SharedA和原始A(sa1)。
答案 2 :(得分:0)
因此,您正在创建可以删除的Stand-In(SharedA)。即使这有点尴尬,我想有必要使用您的遗留API。稍微改进一下:允许从shared_ptr构建SharedA,但不是相反 - 然后只在绝对必须时才使用SharedP:
int main()
{
HelpfulContainer helpfulContainer;
boost::shared_ptr<A> sa1(new A(1));
// deletes its parameter, but that's okay
helpfulContainer.eventHorizon(new SharedA(sa1));
}
答案 3 :(得分:0)
对基础指针类型的隐式转换与shared_ptr
的预期用法不一致,因为您可以非常轻松地将shared_ptr
传递给函数等而不会意识到它。
听起来像我HelpfulContainer
是有用的,应该修复或抛弃。
如果那是不可能的,那么最好的方法就是复制你要传递的A
并将副本传递给容器。