对 boost::smart_ptr 的引用指向对象并检查其有效性
鉴于以下情况:
class Curve {
public:
typedef boost::shared_ptr<Curve> Pointer;
// ...
private:
// ...
};
class CurveShift: public Curve {
public:
CurveShift(const Curve & curve);
// ...
private:
const Curve & curve_;
// ...
};
我想知道当您想做类似的事情时是否有一个共识的最佳实践可以使用:
Curve::Pointer pointer(new Curve());
SomeGlobalRepository::Add("key", pointer);
并且在其他地方您有:
CurveShift cs(*SomeGlobalRepository::Get("key"));
您确实没有任何保证 SomeGlobalRepository
会当 CurveShift
需要它时,包含原始的 Curve::Pointer
,因此 curve_
可能指向已释放的内存,甚至是已经重新分配的内存到别的东西。我相信一种可能的解决方案是 CurveShift
使用 boost:weak_ptr
而不是 const Curve &
,但我我非常确定这意味着您不能再在堆栈上使用 Curve,并且任何实例都必须在堆上(构造函数变为私有,并且通过 工厂)。是否有更好的策略来实现所需的行为?我的直觉是,虽然理论上这可能是一个严重的问题,但实际用例不会造成这些棘手的情况。
Given the following:
class Curve {
public:
typedef boost::shared_ptr<Curve> Pointer;
// ...
private:
// ...
};
class CurveShift: public Curve {
public:
CurveShift(const Curve & curve);
// ...
private:
const Curve & curve_;
// ...
};
I was wondering whether there is a consensus best practice to use when you want to do something like:
Curve::Pointer pointer(new Curve());
SomeGlobalRepository::Add("key", pointer);
And in some other place you have:
CurveShift cs(*SomeGlobalRepository::Get("key"));
You don't really have any assurance that SomeGlobalRepository
will contain the original Curve::Pointer
when CurveShift
will need it, and hence curve_
might point to deallocated memory, or even memory that was already reallocated to something else. I believe that one possible solution would be for CurveShift
to use a boost:weak_ptr<Curve>
instead of a const Curve &
, but I am pretty certain that would mean that you can't use Curve
on the stack anymore, and any instance would have to go on the heap (with the constructors becoming private and the objects being created through a factory). Is there a better strategy to achieve the desired behavior? My gut feeling is that while in theory this could be a serious problem, practical use cases would not lend themselves to creating these tricky situations.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我在您的评论中注意到您在堆栈上分配了一个对象,您想要一个 std::shared_ptr 来...如果是这种情况,您将不得不从堆栈中复制您的对象然后,
这将在堆上分配堆栈对象的副本,并从该堆分配的对象创建一个 std::shared_ptr 。然后,您可以将新创建的共享指针复制到容器等中。
另外,我同意 Nemo 的评论,即您应该让您的类
CurveShift
保存shared_ptr
的副本,而不是比对 Curve 类对象的常量引用...这样,shared_ptr 对象将控制指针引用的生命周期,并且应该是容器或其他对象尝试销毁指向的内存由shared_ptr
实例在其自身解构期间,内存引用仍将保留在CurveShift
实例中,因为在其他地方调用shared_ptr
的析构函数实际上不会释放堆上对象的内存,因为CurveShift
实例对象具有对由shared_ptr
。通过仅保留常量引用,您就消除了使用shared_ptr类型的全部优势,该类型通过某种形式的引用计数来控制在堆上分配的对象的解构。最后,我会为您编写这样的类:
然后您将进行如下调用:
将
shared_ptr
复制到您的CurveShift
实例,并将引用计数增加到其管理的堆上的指针。I noticed in your comments that you have an object allocated on the stack that you want a
std::shared_ptr
to ... if that is the case, you'll have to copy your object from the stack into the heap doing something like:That will then allocate a copy of your stack-object on the heap and created a
std::shared_ptr
from that heap-allocated object. You can then copy your newly created shared pointer into a container, etc.Also I would concur with Nemo's comments that you should have your class
CurveShift
hold a copy of theshared_ptr
rather than a constant reference to aCurve
class object ... that way theshared_ptr
object will control the life-time of the pointer reference, and should a container or some other object try to destroy the memory pointed to by theshared_ptr
instance during it's own deconstruction, the memory reference will still be maintained in theCurveShift
instance since calling the destructor of theshared_ptr
elsewhere will not actually deallocate the memory for the object on the heap as yourCurveShift
instance object has an active reference to that heap allocated object held by theshared_ptr
. By holding just a constant reference, you remove the whole advantage of using ashared_ptr
type which is controlled deconstruction of an object allocated on the heap through some form of reference-counting.In the end, I would write you class like:
And then you would make a call like:
Which copies in the
shared_ptr
to yourCurveShift
instance and increases the reference count to the pointer on the heap its managing.如果您有一个
shared_ptr
,该对象将保持有效。当然,原始参考并不总是有效的。为什么不直接将curve_
设为shared_ptr
呢?weak_ptr
旨在打破循环。我在这里没有看到任何循环,所以应该没有理由。(我认为你的问题中缺少一些限制你的设计的东西)
If you have a
shared_ptr
, the object will be maintained as valid. The raw reference of course is not always going to be valid. Why not just makecurve_
ashared_ptr
?weak_ptr
is designed to break cycles. I don't see any cycles here, so there should be no reason for it.(I think there's something constraining your design here that's missing from your question)