c++: Loki StrongPtr looks unsafe to me, is that so?
I am currently looking at the most popular smart Ptr implementations such as boost shared and weak pointers aswell as loki Smart and Strong pointer 开发者_如何学Pythonsince I want to implement my own and from what I understand Loki Strong pointer looks unsafe to me but I rather think that I understand it wrong so I'd like to discuss whether it's safe or not. The reason why I think it's not safe is that as far as I can tell it does not treat weak Pointers (that is a StrongPtr, where false indicates its weak) with enough care:
for instance the dereferencing functions:
PointerType operator -> ()
{
KP::OnDereference( GetPointer() ); //this only asserts by default as far as i know
//could be invalidated right here
return GetPointer();
}
In a multithreaded environment a weak pointer could be invalidated at any time, so that this function might return an invalidated Ptr.
As far as my understanding goes you would either have to create a strongPtr instance of the ptr you are dereferencing to ensure that it does not get invalidated half way through. I think thats also the reason why boost does not allow you to dereference a weak_ptr without creating a shared_ptr instance first. Lokis StrongPtr Constructor suffers from the same problem I think.
Is this a problem or am I reading the src wrong?
Regarding the use of assert
, it's a programming error to use operator->
on an empty StrongPtr<>
instance; i.e., it is the caller's responsibility to ensure that the StrongPtr<>
instance is non-empty before dereferencing it. Why should anything more than an assert
be needed? That said, if you deem some other behavior more appropriate than assert
, then that's exactly what the policy is for.
This is a fundamental difference between preconditions and postconditions; here's a long but very good thread on the subject: comp.lang.c++.moderated: Exceptions. Read in particular the posts by D. Abrahams, as he explains in detail what I'm stating as understood fact. ;-]
Regarding the thread-safety of StrongPtr<>
, I suspect most of Loki predates any serious thread-safety concerns; on the other hand, boost::shared_ptr<>
and std::shared_ptr<>
are explicitly guaranteed to be thread-safe, so I'm sure their implementations make for a "better" (though much more complicated) basis for study.
After reading carefully, I think I saw the rationale.
StrongPtr
objects are dual in that they represent both Strong
and Weak
references.
The mechanism of assert
works great on a Strong
version. On a Weak
version, it is the caller's responsability to ensure that the object referenced will live long enough. This can be achieved either:
- automatically, if you know that you have a
Strong
version - manually, by creating a
Strong
instance
The benefit wrt std::shared_ptr
is that you can avoid creating a new object when you already know that the item will outlive your use. It's an arguable design decision, but works great for experts (of which Alexandrescu undoubtebly is). It may not have been targetted at regular users (us) for which enforcing that a Strong
version be taken would have been much better imho.
One could also argue that it's always easier to criticize with the benefit of hindsight. Loki
, for all its greatness, is old.
精彩评论