Why use new?

I

Ian Collins

James said:
But in most cases, isn't this more or less obfuscation.
Consider something like:
So you consider std::string's management of its buffer obfuscation?
Most of the time, for entity objects, destruction is the result
of some external event. You can design the system so that it
happens indirectly, e.g. as a result of removing the object from
the objectMap used to find it, or some such, but most of the
time, I would argue that the code is clearer if you do an
explicit delete, and the destructor of the object removes it
from the objectMap at the same time it notifies all other
interested parties (since the object is often in relationship
with other objects, which have to be informed of its demise).
I can see your point, but sometimes it's clearer not to have to worry
about explicit deletion. Also the object may not always be associated
with a container (again, like std::string).
 
P

Paul Brettschneider

James said:
James said:
Paul Brettschneider wrote:
James Kanze wrote:
[...]
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.

That's why I said "with the advent of containers with non-copyable
elements". You have a point with polymorphics, though.
And of course, the standard containers don't use the
new operator either, since they separate allocation and
initialization.

Ok, placement new then.
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

You obviously work on much more complex applications than I do, but what you
describe in response to Ian "feels" like a layering violation to me. Why
should an object know about its containers?

I think it just shows that I come from a RDBMS background and typically I
collect all my objects in containers akin to boost::multi_index_container.
So while you create objects which add themselves to containers, I ask the
container to give me an object of my liking.

I bet your approach is more idiomatic OO/C++, but my code hasn't to be read
by other C++ experts, so it's no problem.
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.

Sure. But you can deal with it by either calling new or delete or by telling
a container to add/delete objects.
And if
the choice of which polymorphic type to use is determined by
the application, application programmers will have to deal with
it.

So far I only had to deal with simple polymorphics and I would generate them
on the stack and pass them down to some container, which would then use the
virtual clone() method (which does of course use new).
(This probably sounds perverse to C++ veterans. ;))
 
J

James Kanze

Paul Brettschneider a écrit :
James Kanze wrote:

[...]
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
You obviously work on much more complex applications than I
do, but what you describe in response to Ian "feels" like a
layering violation to me. Why should an object know about its
containers?

Because part of the object's semantics are that it can be
"found" by some external identifier. Ideally, you're right, of
course, and one could imagine using some variant of the observer
pattern, but for application level objects, I think it's usually
overkill. The object is designed to work at part of the
application, and the fact that the application uses some
specific object map is part of that application. Most of the
time, it will in fact be "partially" hidden, in the sense that
the object simply enrols and deenrols with some sort of
"dictionary", but that's really only partial hiding.
I think it just shows that I come from a RDBMS background and
typically I collect all my objects in containers akin to
boost::multi_index_container. So while you create objects
which add themselves to containers, I ask the container to
give me an object of my liking.
I bet your approach is more idiomatic OO/C++, but my code
hasn't to be read by other C++ experts, so it's no problem.

Well, it's more idiomatic in the places I've worked in, but I
think you have a valid point when you say that having the object
know about the lookup service breaks encapsulation to some
degree. Or course, a lot of objects have to know about it
anyway, since they will use it as a client, and not just for
enrolling themselves. But I think the main reason that it's
widely used is that the breach of encapsulation has never been
felt to be enough of a problem for someone to look for a good
solution.
Sure. But you can deal with it by either calling new or delete
or by telling a container to add/delete objects.

Sure. But that's sort of my point. If the application wants to
delete an object, the most obvious way is "delete object";
something like "objectMap.erase( object->id() )" seems a bit
more indirect, and makes it less obvious what is actually
happening.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,176
Messages
2,570,947
Members
47,498
Latest member
log5Sshell/alfa5

Latest Threads

Top