In article <11*********************@u72g2000cwu.googlegroups. com>,
"Divick" <di************@gmail.com> wrote:
I would suggest you avoid manually managing scope where possible. Even
a simple boost::scoped_ptr is preferable. Also, if lifetime tracking is
an issue, then take a good long look at boost::weak_ptr. The
shared_ptr/weak_ptr combo has become an integral part of my run-time
polymorphic class design, it just saves so many headaches.
I have several questions with respect to smart pointers, since you and
others as well have advised to use them.
1. Is shared_ptr and other smart pointers thread safe? I am planning to
use them in a threaded and multiprocessor environment.
2. I don't want to expose to the client programmer that the return type
of some method is a boost::smart_ptr because the client programmer
might not be conversant with the smart pointers and I do not want him
to delve into how I handle the pointes internally in my API. If I do a
typedef the types like typedef HANDLE boost::shared_ptr<MyClass> then I
will need to document that the client programmer can use that HANDLE as
he would use pointer to MyClass, but it might confuse him altogether.
So the question really is "Is it a good idea to expose to the end user
the boost types as return values?"
3. Since boost pointers require the template class passed should have
the destructor as public, but what if I need to have a class with
protected destructor?
But, as suggested above, first try and analyse the lifetime of B's if
possible. In library design lifetime analysis is often difficult
because you need to make some assumptions about how your library will
be used.
As far as managing lifetimes are concerned, I understand that passing
as reference is fine in the method parameters if the function is not
going to store the object. Since references to objects on stack
automatically get deleted due to scope, there is no problem or
ambiguity.
The problem really comes when you need to return pointers or objects
from functions and when you need to store the pointers/objects. My API
needs to return objects/pointers to the client programmer of some
objects created by my Factory classes.
As far as managing lifetimes are concerned, anytime you have more than
one pointer/reference pointing/referring to the same object, you have to
worry about when the destructor will be called on that object and make
sure that both holders know when that will be. *EVEN* when you pass a
pointer/reference in a method parameter and you don't plan on storing it
past the end of that method. (In a multi-threaded situation, for
example, the objects delete could be called in the middle of your
method.)
One way to solve the problem is to make sure only one reference/pointer
is connected to every object. As such, I would recommend against you
passing a reference to an object to the client *and* storing it in the
server class. IE:
A& createObjA()
{
A &b = *(new B()); //B subclasses from A
//Store the b somewhere because the object b is some system resource
//which I need to keep track of.
// code to store object b somewhere
return b;
}
Is a bad idea. I will go so far as to say that the only time a function
should return a modifiable reference is if it returns '*this' (or if you
are writing a basic container class.) In all other cases, if returning
something it should return an object, const object&, or object* (either
const or non-const). In the later case, make it clear who is supposed to
delete the actual object and exactly when that will happen. The choices
are:
1) The client must delete it, and can do so any time it likes.
2) The client must *not* delete it. Instead, the server will delete it
when particular functions are called (and in its destructor.)
If the function returns a const object&, then it should be made clear
that the server class can destroy the object by the time any other
member function is called. IE returning by const object& should be
thought of only as an optimization over turning by object.
Given these rules, the below is fine:
A* createPtrA()
{
A *a = new B();
return a;
}
As long as the documentation for the function makes it clear that it is
the caller's responsibility to delete the object (choice 1 above.) Some
go so far as to wrap it in an auto_ptr, as in:
auto_ptr<A> createPtr() {
return auto_ptr<A>( new B );
}
--
Magic depends on tradition and belief. It does not welcome observation,
nor does it profit by experiment. On the other hand, science is based
on experience; it is open to correction by observation and experiment.