Re: Raw pointers not evil after all?
On 5/2/2013 12:17 PM, James Kanze wrote:
On Thursday, 2 May 2013 02:03:00 UTC+1, Christopher Pisz wrote:
[...]
The owner should be the class that allocated the
object.
If the owner should be the class which allocated it, why bother
with dynamic allocation.
Usually, because
1) Size is unknown
2) It is an an interface rather than concrete
3) Storing, passing, and manipulating pointers is more optimal than
copying a large object by value and references weren't an option.
There are some exceptions, when
a class implements a dynamically sized structure (like
`std::vector`), but most of the time, the reason you're
allocating dynamically is that the object has an arbitrary
lifetime of its own, which may excede that of the object which
creates it.
I haven't found that to be the 'usual' case. I'd need a specific
example, but I try my best to make sure that any allocated object
is at least conceptually owned by someone if not really owned by
someone. No rule of the language or any textbook is going to say one way
or the other.
Perhaps, my real meaning behind the word "owned" is more abstract than
your meaning? We'd probably have to talk about specific examples for
clear communication.
And why this insistence on ownership. In many application, the
most important objects aren't (or shouldn't be) owned by anyone.
Maintenence, readability, all those words people can argue about.
I am curious as to why you would say, "shouldn't be owned by anyone"
Why not?
The object itself manages its lifetime, in response to whatever
external events it waits one. (Who "owns" the window object in
a GUI application?) Or the objects are created by some sort of
factory (which certainly doesn't "own" them).
In native C++ applications that use the Windows API, I personally have
an Application class whom creates the windows, has a member that is the
Window procedure, and members that the Window makes use of, including
the handle itself. So, my Application class owns the Window. In turn,
the main function owns the Application instance. The Application class
instance owns and manages the lifetime of the Window.
In the factory example, I'd say take my meaning of "owned" less
literally. Some called a Create or some such method on the factory, got
back and instance to an object, and either owns it, or is going to
promptly give it to someone to own. When I say, "own" I mean that when I
am debugging, I know where it came from and whom is going to release it
when, it doesn't just float around where the programmer "hopes" it gets
released when everyone is done with it at some unknown point in time.
void Foo()
{
boost::shared_ptr<IMyInterface> someInterface = MyFactory.Create(1,
2, 3);
try
{
someInterface->DoStuff();
}
catch(common::BaseException & e)
{
m_logger(e.Message());
}
}
In the above, Foo owns it, its lifetime is clear, it will be destroyed
when an exception occurs and the stack unwinds or the function returns.
What I don't like, and again this is my opinion and isn't in any textbook:
void Foo()
{
boost::shared_ptr<IMyInterface> someInterface = MyFactory::Create(1,
2, 3);
global_a.m_interface = someInterface;
global_b.m_interface = someInterface;
global_c.m_interface = someInterface;
}
Now, it is unclear when the instance of someInterface will be destroyed.
The author just depended on the reference counting to take care of it
for him and ignored the lifetimes of a, b, and c, probably didn't check
for cyclic references, and probably didn't check what will happen at
program exit. Not sure if those examples are the best to try and get
what I am trying to communicate across....