Reputation: 4980
I'm referring to Refbase.h, Refbase.cpp and StrongPointer.h
In the Android implementation of strong pointer, any strong-pointer based object must inherit refbase i.e.
sp<TheClass> theObj // TheClass must inherit from class RefBase
This requirement can be seen in the code for one of sp
's methods:
template<typename T> sp<T>& sp<T>::operator =(T* other) {
if (other != NULL) {
other->incStrong(this);
}
if (mPtr != NULL) {
mPtr->decStrong(this);
}
mPtr = other;
return *this;
}
In order for call to incStrong
or decStrong
to not fail . . . other
and mPtr
must have inherited RefBase
QUESTION
Why is sp
implemented such that the obj that it's managing is required to be a child of RefBase
? There's not even a way to enforce this requirement at compile-time or even runtime. (Well maybe if(type()...
)
Std library doesn't have such a requirement
...
Upon further thought, is the answer that this provides flexibility?
If yes, how does this provide flexibility?
Upvotes: 4
Views: 5377
Reputation: 724
It automatically allows you to create sp from any object implementing RefBase, while for shared pointer you can shoot yourself in the foot while trying to wrap raw pointer into shared one.
So while for shared_ptr you might need this: http://en.cppreference.com/w/cpp/memory/enable_shared_from_this
for sp you can almost safely pass raw pointer to sp contructor.
Upvotes: 0
Reputation: 29017
It saves a memory allocation. When you write:
std::shared_ptr<Foo> pFoo{new Foo(bar)};
pFoo
actually has a pointer to a shared data structure (allocated on the heap), which has the reference counters, and the pointer to the actual Foo object. By making objects be derived from RefBase
, you can embed the reference counts in the object itself (saving the additional memory allocation).
Interestingly, with C++11 onwards, you can avoid the additional memory allocation by using std::make_shared<Foo>
which will do a single memory allocation and construct the shared data structure and the Foo object in it.
The fact there is no compile time checking of the derivation from RefBase
is carelessness. m_ptr
should have been declared as RefBase *m_ptr
, and then operator *
(etc) should have done a static_cast to T*
. In fact, I would probably have made sp<T>
inherit from sp_base
which had the comparison operators as public, and the other functions as protected.
Edit
On second thoughts, there is quite a bit of compile time checking. If T
doesn't have an incStrong
member, the compilation will fail, and it almost certainly won't unless it derives from RefBase
. I still think converting a T*
to a RefBase*
would have been a better check, but the one that is there is probably good enough.
Upvotes: 2