|
Boost : |
From: Oleg Fedtchenko (BoostOleg_at_[hidden])
Date: 2004-10-15 03:12:32
>> Oleg Fedtchenko wrote:
>>
>> shared_ptr<Tree> Parse( shared_ptr<DocActiveX> ptrOwner)
>> {
>> shared_ptr<Tree> ptrMember( &m_Tree, ptrOwner);
>> return ptrMember;
>> }
>>
>> And corresponding ctor that passes over a deletable pointer to an
>> owner (ptrOwner) of a class member (p):
>>
>>
>> template <class Y, class Z>
>> shared_ptr( Y * p, shared_ptr<Z>& ptrOwner)
>> : px(p), pn(ptrOwner.pn)
>> {...}
>>
>> But it's good if this class will never be used as an object
>> (nondynamic) data-member inside another owner.
>>
>> Also it's good when we create shared_ptr using ptrOwner outside
>> a class because we can pass in a shared_ptr of any owner.
> Larry Evans wrote:
>
> This is unclear to me. Could you provide an example?
The Parse above is a function-member of a class DocActiveX (I forgot
to specify this). Therefore shared_ptr ptrOwner has DocActiveX as
its parameter.
But if an object of DocActiveX is a member of another class like this:
class Superclass
{
public:
DocActiveX doc;
};
then parameter ptrOwner in the function DocActiveX::Parse (see above)
must be of type shared_ptr<Superclass>:
shared_ptr<Tree> Parse( shared_ptr<Superclass> ptrOwner)
{
shared_ptr<Tree> ptrMember( &m_Tree, ptrOwner);
return ptrMember;
}
because ptrOwner is what ought to be deleted when all shared_ptr's to
m_Tree are released.
To resolve this issue the function Parse accepting owner of any type
can be written in a templated form:
template <class Z>
shared_ptr<Tree> Parse( shared_ptr<Z> ptrOwner)
{
shared_ptr<Tree> ptrMember( &m_Tree, ptrOwner);
return ptrMember;
}
But such a templated function has its own drawbacks, and there is an
alternative to it. Please, read this email
http://lists.boost.org/MailArchives/boost/msg73234.php
on that.
The issue about the owner type doesn't raise when shared_ptr to a member
is created outside a class containing that member
(e.g. inside an actual owner):
Tree* Parse()
{
Tree* ptrMember = &m_Tree;
return ptrMember;
}
void SomeClass::SomeFunc()
{
...
shared_ptr<Superclass> pSuper(new Superclass);
...
shared_ptr<Tree> ptrTreeHere( pSuper->doc.Parse(), pSuper);
ptrTreeHere->SomeFunc();
...
}
But we can easily by mistake put some wrong owner instead of *pSuper*:
shared_ptr<Tree> ptrTreeHere( pSuper->doc.Parse(), this);
// it's wrong because *this* cannot be deleted on destructing ptrTreeHere
//
// only dynamically allocated owner can be passed in the Parse
// and *this* can point to an object data-member (nondeletable using
// op *delete*) of some other class
And the next is clearer, isn't it?
And Parse below can have the only instance (as it's not templated).
member_ptr<Tree> Parse()
{
member_ptr<Tree> ptrMember( &m_Tree);
return ptrMember;
// deletable owner of m_Tree gets into ptrMember
// from m_Tree inside its CTOR
}
void Superclass::SomeFunc()
{
...
doc.Parse()->SomeFunc();
...
}
The proposed smart pointer member_ptr is described at
http://boostoleg.narod.ru/member_ptr.html
Oleg Fedtchenko
recommended thread entry
http://lists.boost.org/MailArchives/boost/msg73168.php
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk