[comp.lang.c++] Why redefine operator new if you do not have to?

wgh@ubbpc.UUCP (William G. Hutchison) (09/18/90)

 We have a problem here in the Philadelphia area. No, I do not
mean that Philadelphia's municipal bonds have a rating of 'B' :-{

 The president of a local software firm has taken it upon himself to make
public lectures about C++.  He bought Turbo C++ a few weeks ago and he
has not yet finished reading the Annotated C++ Reference Manual (!!).

 This gent is an accomplished C programmer, and I do not want to embarrass
him more than necessary, so I will refer to him as 'Joe' (not his name).

 Joe has been using an 'infinite precision' integer package as an example
in his talks.  He has presented a C version, and he is now discussing how
to implement the package as a C class called Number.

 He is doing OK except on the subject of constructors.  Joe has some weird
concept that a constructor should do type conversion, like
Number(int), but that a different technique is needed for storage allocation,
as in "allocate a 10-digit Number".  Joe thinks that a cool way to do
storage allocation for Number is to define his own Number::operator new().

 I explained that new() was already set up for class Number, and he does not
have to redefine it, and that redefining new() is for replacing the allocation
mechanism, and that Number(int x=0) is a good constructor and that it is
never necessary to allocate an empty Number in advance (the storage can
be allocated as needed).

 But Joe just doesn't get it.  How can I explain this to a beginner who thinks
he is an expert in C++ because he knows C real well and he has read half a book
on C++? 

 By the way, Joe has never heard of libg++ and he thinks that GNU software is
low quality hacker stuff.  His ego will not allow him to accept that the GNU
folks write better code than he ever did.

 I plan to print out your responses to this query and distribute them at the
next session of the computer association next month.

 Thank you for your support!
-- 
Bill Hutchison, DP Consultant	rutgers!cbmvax!burdvax!ubbpc!wgh (work)
Unisys UNIX Portation Center	uunet!eidolon!wgh (home)
P.O. Box 500, M.S. B121         "At the moment I feel more like arguing than
Blue Bell, PA 19424		being good" Raymond Smullyan _The Tao is Silent_

daniel@terra.ucsc.edu (Daniel Edelson) (09/19/90)

In article <749@ubbpc.UUCP> wgh@ubbpc.UUCP (William G. Hutchison) writes:
>
> Joe has been using an 'infinite precision' integer package as an example
>in his talks.  He has presented a C version, and he is now discussing how
>to implement the package as a C class called Number.
>
> He is doing OK except on the subject of constructors.  Joe has some weird
>concept that a constructor should do type conversion, like
>Number(int), but that a different technique is needed for storage allocation,
>as in "allocate a 10-digit Number".  Joe thinks that a cool way to do
>storage allocation for Number is to define his own Number::operator new().

Since 2.0, if I correctly grok things, the language designer
(motion of hat tipping) has emphasized the distinction between 
construction and allocation. Allocation is the process of obtaining
store for an object. Construction is the act of putting
an object into a consistent initial state. Clearly allocation must
occur before construction.

I believe here that Joe is confusing allocation of the Number, with
allocation of the components of the Number. The number consists of
a pointer to a linked list of digits, I expect. It's size is 4 bytes
for the pointer. That is independent of the number of digits. So the
sizeof(number of 1 digit) is equal to the sizeof(number of 8 digits).
Allocation of the Number happens before its construction. 
Allocation of the linked list that implements the number
happens during construction of the number. 
Read on.

> I explained that new() was already set up for class Number, and he does not
>have to redefine it, and that redefining new() is for replacing the allocation
>mechanism, and that Number(int x=0) is a good constructor and that it is
>never necessary to allocate an empty Number in advance (the storage can
>be allocated as needed).

You are correct.
The operator ``new'' is used to obtain store from the free store (heap).
This accomplishes allocation. 
Local variables are allocated on the stack. 
Global variables are allocated from global data. 
So ``new'' is only needed for the allocation of dynamic objects. 
These are objects whose lifetime is under the explicit 
control of the programmer. This is useful in a
number of places:
	- when the total number of objects required is unknown at compile
	  time, as in any dynamic data structure such as a graph or a list
	- when the size of an object is unknown at compile time, such as
	  a vector
	- if neither of the above is true, then when an object's lifetime is 
	  neither the life of the program, nor the life of one function
	  activation

Joe's project is an arbitrary precision integer class. How many digits
are required to represent such a number? Obviously that cannot be
determined at compile time. So some dynamic data should be used in 
the implementation of the class? Should operator new be overloaded?
To answer that Joe must understand what overloading new and delete
accomplishes.

Operator new is used for allocation. It obtains n bytes of space
from somewhere and returns a pointer to them. The default operator
new obtains space from a common pool of memory (the free store) 
shared by all the modules of the program. This is a general purpose
memory allocator, which on some systems might simply be implemented
with a call to malloc. Suppose a programmer knows that dynamically
allocated objects are free'd in waves, for example, objects are
allocated, then all the objects are deleted. More are allocated, then
all of them are deleted. I've seen this behavior in a compiler where
processing is performed on a per-function basis. After generating icode
for the function the compiler frees all the temporary objects it used
in one swell foop, rather than individually with delete or free().
In this case, a general purpose allocator is unnecessarily 
inefficient. A more efficient allocator would allocate
objects, and then upon command recycle the entire space. This is
basically what copying collectors do.

This, basically, is what overloaded operators new and delete are for.
To implement a customized dynamic memory management policy, and make
it available to clients transparently. Clients of the package need
not invoke some special allocator, such as:
	void * alloc_special(char * store, int nbytes);
They just use the normal operator new syntax. You've provided the
the customized allocator.

Overloaded operator new is used primarily to allocate objects
from a dedicated pool of memory, other than the general pool shared
by all dynamic data. This can be used to accomplish conservative garbage 
collection quite straitforwardly. Copying or mark-and-sweep garbage
collection requires more support than C++ currently provides because the
collector must be able to distinguish pointers from integers.

> But Joe just doesn't get it.  How can I explain this to a beginner 
> who thinks he is an expert in C++ because he knows C real well and he 
> has read half a book on C++? 

Beat him about the ears with soggy spaghetti and say:
	``Do not overload new unless you know what it's for!
	  Do not overload new unless you know what it's for!''

Learning C++ philosophy and style from the ARM is like
learning ADA from the ironman. It's not a tutorial,
it's a reference. I suggest that your friend obtain a 
copy of ``C++ for Pascal Programmers'' by Pohl, published by
Benjamin-Cummings, 1991, and ignore the first two chapters on 
Pascal and C. 

I've been using C++ for 4 years and have barely a clue.
If he learned C++ philosophy and style from half of the ARM 
then he's a better man than me gungadin. (not too tough anyway)

So, should Joe be overloading operator new? What is Joe allocating
dynamically? I suspect that the dynamic objects are the list nodes
that are internal to the numbers. These must be allocated in the 
constructor(s), and undoubtedly in overloaded operators. Must
these list nodes come from a special, dedicated pool of memory?
I see no reason why they should. So, should Joe overload operator
new? I believe not.

``>..., and that Number(int x=0) is a good constructor and that...''

It looks like a very good constructor to me! He'll also need a
copy constructor:
	Number::Number(const Number &);
if he permits the client to have any functions that take 
by-value Numbers or that return Numbers (not Number&'s).
If the client is not permitted to pass Numbers by value (for efficiency)
then the copy constructor should be prototyped as private, 
to enforce the prohibition.

> By the way, Joe has never heard of libg++ and he thinks that GNU software is
>low quality hacker stuff.  His ego will not allow him to accept that the GNU
>folks write better code than he ever did.

I bet that I'm not the only one who's going to respond to this posting.

> I plan to print out your responses to this query and distribute them at the
>next session of the computer association next month.

I hope my posting doesn't empty your printer of paper.

> Thank you for your support!
>-- 
>Bill Hutchison, DP Consultant	rutgers!cbmvax!burdvax!ubbpc!wgh (work)
>Unisys UNIX Portation Center	uunet!eidolon!wgh (home)
>P.O. Box 500, M.S. B121         "At the moment I feel more like arguing than
>Blue Bell, PA 19424		being good" Raymond Smullyan _The Tao is Silent_

I apologize for going on with such verbosity about allocation and
operator new. I figured that anyone who got sick of it would just hit
the old `n' key. (possibly 99.99%) of the audience. But I thought I
might be able to offer a comprehensible answer to this question.
I hope the fairly lengthy explanation convinces Joe that 
overloading operator new would be an unnecessary and useless 
complication.

Good luck convincing him, and getting a really elegant first C++ 
package from a new C++ programmer.
---
Daniel Edelson                   |  C++ virtual garbage recycler:
daniel@cis.ucsc.edu, or          |    ``Recycle your garbage. Please don't
 ...!sun!practic!peren!daniel    |    make me come and copy after you.'' 

bright@Data-IO.COM (Walter Bright) (09/20/90)

In article <749@ubbpc.UUCP> wgh@ubbpc.UUCP (William G. Hutchison) writes:
< I plan to print out your responses to this query and distribute them at the
<next session of the computer association next month.

Why not just give the responses to him privately well in advance of his
lecture? Give the poor guy a break.