References to boost::smart_ptr pointed to object and checking their validity
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 ach开发者_运维百科ieve 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.
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:
std::shared_ptr<my_object_t> sh_ptr(new my_object_t(stack_object));
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 the shared_ptr
rather than a constant reference to a Curve
class object ... that way the shared_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 the shared_ptr
instance during it's own deconstruction, the memory reference will still be maintained in the CurveShift
instance since calling the destructor of the shared_ptr
elsewhere will not actually deallocate the memory for the object on the heap as your CurveShift
instance object has an active reference to that heap allocated object held by the shared_ptr
. By holding just a constant reference, you remove the whole advantage of using a shared_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:
class CurveShift: public Curve {
public:
CurveShift(const shared_ptr<Curve>& ptr): _curve(ptr)
{
// ... rest of constructor
}
private:
shared_ptr<Curve> curve_; //will remain valid for lifetime of CurveShift instance
// ...
};
And then you would make a call like:
CurveShift cs(SomeGlobalRepository::Get("key"));
Which copies in the shared_ptr
to your CurveShift
instance and increases the reference count to the pointer on the heap its managing.
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 make curve_
a shared_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)
精彩评论