James said:
Paul said:
[...]
But when are there any reason to use new?
Lots. Most of the time, you use new because you need an
explicit lifetime for the object. You create it in some low
level function, in response to an external event, and you delete
it in some other low level function, in response to some other
external event.
I guess with the advent of containers with non-copyable
elements, more and more of those new() calls will be hidden in
std::container::insert() calls and the like.
I'm not sure what containers you're talking about, but I very
much doubt that any of the calls to new would be found in their
insert() functions.
In the scenario I described (a very, very frequent one for
servers, GUI's and probably a number of other applications), the
new is in response to an external event, as is the delete.
Containers don't repond to external events.
My idea was that you will have code like this (totally made up
this moment):
Handle open_window(const std::string &title)
{
extern std::map<Handle, Window> Windows;
Handle h(Windows); // Generates unique handle
Window &w = Windows[h];
w.set_title(title)
return h;
}
Which, of course, typically won't work, because classes like
Window typically don't support copy. Also, they are
polymorphic, so the actual type will be something derived from
Window. And of course, the standard containers don't use the
new operator either, since they separate allocation and
initialization.
Generally speaking: if an object has an explicit lifetime, it
almost always also has identity, and so won't support copy, and
can't be put in a standard container. And the standard
containers don't support polymorphism either. There are cases
where it might be appropriate to have a container own an object,
i.e. by containing it via some sort of smart pointer, but they
are fairly rare. Most of the time, the container is at the
service of some higher level concept, and it is the
implementation of the higher level concept (often the object
itself) which takes charge of managing object lifetime.
Here the new() is hidden in operator[] of std::map. IMHO new
and delete are low-level functions (or call them operators)
and application developers should not have to care too much
about them. But maybe I'm just silly?
Maybe. In the applications I work on, or have worked on (large
scale servers, mostly, but also one GUI framework), the
application had to deal with arbitrary lifetimes of entity
objects, and with polymorphic objects, whereas the lower levels
mainly dealt with value objects, or just shuffled pointers
around, and used templates more than dynamic allocation. If the
lifetime of an object is part of the application design, then
the application programmers will have to deal with it. And if
the choice of which polymorphic type to use is determined by
the application, application programmers will have to deal with
it. In my experience, the higher you go in the abstraction
levels, the more the new operator becomes relevant. (There are
some low level structures where it would be relevant as well,
things like graphs and such. I've not had to deal with them
much myself, however.)