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.