[comp.lang.c++] Why no renew

hoff@bnlux0.bnl.gov (Lawrence T. Hoff) (02/08/91)

    I haven't seen this question posted before, but I've only just started
reading this newsgroup, I apologize in advance if it is a FAQ.

    When I am coding an algorithm which requires dynamic memory allocation,
but the total memory requirements are not known in advance, I use
realloc(), rather than malloc()/copy/free(), because realloc is generally
more efficient in that data is only copied if necessary, i.e. is sufficient
contiguous memory in unavailable. As posted many times here recently, 
new should always be used with delete, and malloc/realloc should always
be used with free. One should not mix these allocation schemes. 

    My question is : Is there a 'renew' operator, i.e. a function which
acts like realloc, but works with memory allocated with the new operator?
If not, why not? 

    Some caveats come to mind, mostly they seem to follow the same theme : 
This (renew) is potentially dangerous, one would have to exercise extreme 
caution. However, this seems no more dangerous than realloc(), especially when
when dealing with intrinsic data types rather than arrays of class objects.
When dealing with arrays of class objects, there is of course the question
of how to do the copy (bitwise copy, assignment, or destroy/contruct), 
otherwise I can't see any fundamental reason this would not be possible 
to implement, with the caveat that whatever copy scheme was used might
not work with certain class objects.

    Of course, I can accomplish what I want to do with a new/copy/delete
operation, chossing the most approprite copy scheme for the data type in
question, but why sacrifice efficiency when it's not necessary. I WILL 
concede that one should perhaps not be concerned with efficiencies to any
great extent when one is dealing with dynamically allocated memory,
however this IS exactly why realloc() exists.

    Comments? 

jbuck@galileo.berkeley.edu (Joe Buck) (02/08/91)

[ a proposal for a "renew" operator that works like realloc ]

You're free to propose a "renew" operator as an extension if
you want, but remember that new is not equivalent to malloc,
and delete is not equivalent to free; new calls a constructor
and delete calls a destructor.  Often an object contains pointers
to other dynamic objects, so the delete call causes other
delete calls.  What would renew do?  Presumably you still need
a destructor and a constructor call.  Would it do these and then
try to use the same block of allocated memory?  If that's what
you want, you could implement it by overloading the new and
delete operators for the class where you want to get realloc()-
style behavior.  The idea would be this: the delete operator
would keep the last block deleted, and new would try to use it
if possible.  Here's an example of an implementation:


class MyClass {
public:
	// other stuff
	void* operator new (size_t);
	void operator delete (void*, size_t);
private:
	static void* lastBlock;
	static size_t lastBlockSize;
}
void* MyClass :: operator new (size_t size) {
	if (lastBlockSize == 0) return malloc(size);
	else if (lastBlockSize >= size) {
		lastBlockSize = 0;
		return lastBlock;
	}
	else {
		free(lastBlock);
		lastBlockSize = 0;
		return malloc(size);
	}
}

void MyClass :: operator delete (void* p, size_t size) {
	if (lastBlockSize > 0) free(lastBlock);
	lastBlock = p;
	lastBlockSize = size;
}

I think this kind of stuff can give you whatever advantages
you wanted from realloc(), and it's isolated from the rest of
the program.  Overloading new and delete on a per-class basis
means that you can tune memory allocation however you want.
--
Joe Buck
jbuck@galileo.berkeley.edu	 {uunet,ucbvax}!galileo.berkeley.edu!jbuck	

chip@tct.uucp (Chip Salzenberg) (02/09/91)

According to jbuck@galileo.berkeley.edu (Joe Buck):
>You're free to propose a "renew" operator as an extension if
>you want, but remember that new is not equivalent to malloc,
>and delete is not equivalent to free; new calls a constructor
>and delete calls a destructor.

How about a renew that is defined only for arrays?  The "delete [] p"
statement requires that the size of the allocated arrray be remembered
by the implementation.  So renew has the information it needs to call
constructors and destructors appropriately.

I would like to see something like:

     class X { ... };
     X *p = new X[1];         // calls p[0].X::X()
     p = renew(p, 2);         // calls p[1].X::X()
     p = renew(p, 1);         // calls p[1].X::~X()
     delete [] p;             // calls p[0].X::~X()

Remember that the current definition of "::operator new()" loses all
type information, so we need some language support for this feature to
work.

How about it?
-- 
Chip Salzenberg at Teltronics/TCT     <chip@tct.uucp>, <uunet!pdn!tct!chip>
 "Most of my code is written by myself.  That is why so little gets done."
                 -- Herman "HLLs will never fly" Rubin

horstman@mathcs.sjsu.edu (Cay Horstmann) (03/03/91)

In article <10895@pasteur.Berkeley.EDU> jbuck@galileo.berkeley.edu (Joe Buck) writes:
>[ a proposal for a "renew" operator that works like realloc ]
>
>You're free to propose a "renew" operator as an extension if
>you want, but remember that new is not equivalent to malloc,
>and delete is not equivalent to free; new calls a constructor
>and delete calls a destructor.  Often an object contains pointers
>to other dynamic objects, so the delete call causes other
>delete calls.  What would renew do?  

(stuff deleted)

It is abundantly clear what renew should do. If the size of the renewed block
is larger than the size of the current block, grow the current block (if
possible) or copy the elements over with a bitwise copy to a new block, then 
RUN THE DEFAULT CONSTRUCTOR on the remaining (new) elements. 

If the renewed block is smaller, the top elements of the current block
should be passed to the destructor. 

Note that this cannot be easily done with the array version of operator new.
You must write some code like
     X* newptr = new X[newsize]; // runs the constructor newsize times
     for( int i = 0; i < oldsize; i++ )
	  newptr[i] = oldptr[i]; // runs X::operator= oldsize times
     delete[] oldptr; // runs the destructor oldsize times
Clearly this is less than efficient. Contrast with a renew operator which
just runs the default constructor newsize-oldsize times. 

I have a parametric variable array class that fakes the renew feature by
allocating new char[size*sizeof(X)], then runs constructors and destructors
with the placement syntax on each array element when necessary. But it
doesn't work for non-class types (int's, pointers) or class types without
both X::X(), X::~X() (e.g. Complex.) That is a real pain. 

SINCE I AM AT IT: It would be awful nice if operator new could zero out
the memory when allocating arrays of integers or pointers (i.e. fill the
array with the bit pattern corresponding to a logical zero.) Performance
impact should be minimal, and since ints etc. don't have constructors,
there is no good way for the programmer to achieve the same effect. This 
suggestion surely doesn't break any existing code. 

Cay

bright@nazgul.UUCP (Walter Bright) (03/12/91)

In article <1991Mar3.053504.14027@mathcs.sjsu.edu> horstman@mathcs.sjsu.edu (Cay Horstmann) writes:
/SINCE I AM AT IT: It would be awful nice if operator new could zero out
/the memory when allocating arrays of integers or pointers (i.e. fill the
/array with the bit pattern corresponding to a logical zero.)

Ah, but you can do it! Simply overload the global operator new to use
calloc. It's even portable!

horstman@mathcs.sjsu.edu (Cay Horstmann) (03/14/91)

In article <281@nazgul.UUCP> bright@nazgul.UUCP (Walter Bright) writes:
>In article <1991Mar3.053504.14027@mathcs.sjsu.edu> horstman@mathcs.sjsu.edu (Cay Horstmann) writes:
>/SINCE I AM AT IT: It would be awful nice if operator new could zero out
>/the memory when allocating arrays of integers or pointers (i.e. fill the
>/array with the bit pattern corresponding to a logical zero.)
>
>Ah, but you can do it! Simply overload the global operator new to use
>calloc. It's even portable!

I cannot call such a solution portable. 

If my code relies on the global operator new doing one thing and your
code relies on the global operator new doing something different, we cannot
share code for the same program. (The ARM [p.60] has a similar comment.)

I repeat my request that operator new should default to initializing the
memory with the logical 0 value for the type allocated (almost always an
all-0 bit pattern, but then who knows how 0 pointers or 0.0 floats are
represented on some crazy systems.) ANSI, are you listening?

Cay

daves@ex.heurikon.com (Dave Scidmore) (03/15/91)

In article <1991Mar14.042611.14921@mathcs.sjsu.edu> horstman@mathcs.sjsu.edu (Cay Horstmann) writes:
>In article <281@nazgul.UUCP> bright@nazgul.UUCP (Walter Bright) writes:
>>Ah, but you can do it! Simply overload the global operator new to use
>>calloc. It's even portable!
>
>I cannot call such a solution portable. 
>
>If my code relies on the global operator new doing one thing and your
>code relies on the global operator new doing something different, we cannot
>share code for the same program. (The ARM [p.60] has a similar comment.)
>
>I repeat my request that operator new should default to initializing the
>memory with the logical 0 value for the type allocated (almost always an
>all-0 bit pattern, but then who knows how 0 pointers or 0.0 floats are
>represented on some crazy systems.) ANSI, are you listening?

I think that *not* zeroing out memory should be the default. My reasons are
as follows: 

	1) Zeroing is infrequently needed and seldom even helpful.

	2) Any values needing initialization can be initialized
	   by the constructor for the object.
	   
	3) Frequently the overhead for the constructor performing
	   the initialization is little more than that required for
	   initialization at allocation time.
	
	4) If initialization needs to be done field by field then extra
	   code is added to the constructor to perform that initialization.
	   This would be code which is often not needed.

	5) Initialization of objects at allocation time adds time to
	   the allocation of *every* object when it is needed for
	   only a few objects.

	6) For large objects such as buffers in the megabyte range
	   initialization time can result in visible delays while
	   buffers are allocated. For such buffers initialization
	   is usually not needed.

	7) In addition to global operator new an objects operator new can
	   be overloaded to initialize the memory if needed

In summary it is my opinion (not that my opinion counts) that initialization
of object upon allocation is of dubious benefit, and so is a waste of time
and possibly code. I would prefer to see the spec remain the same. ANSI, are
you listening?
--
Dave Scidmore, Heurikon Corp.
dave.scidmore@heurikon.com

horstman@mathcs.sjsu.edu (Cay Horstmann) (03/17/91)

In article <184@heurikon.heurikon.com> daves@ex.heurikon.com (Dave Scidmore) writes:
>In article <1991Mar14.042611.14921@mathcs.sjsu.edu> horstman@mathcs.sjsu.edu (Cay Horstmann) writes:
>>
>>I repeat my request that operator new should default to initializing the
>>memory with the logical 0 value for the type allocated (almost always an
>>all-0 bit pattern, but then who knows how 0 pointers or 0.0 floats are
>>represented on some crazy systems.) ANSI, are you listening?
>
>I think that *not* zeroing out memory should be the default. My reasons are
>as follows: 
>
>	1) Zeroing is infrequently needed and seldom even helpful.

Huh? When you say X** a = new X*[100], isn't it most likely that you want
all those X*'s to be null pointers?
>
>	2) Any values needing initialization can be initialized
>	   by the constructor for the object.

I was talking about new applied to NON-CLASS TYPES. They don't have
a constructor.
>	   
>	3) Frequently the overhead for the constructor performing
>	   the initialization is little more than that required for
>	   initialization at allocation time.
>	

Ditto.
>	4) If initialization needs to be done field by field then extra
>	   code is added to the constructor to perform that initialization.
>	   This would be code which is often not needed.
>
>	5) Initialization of objects at allocation time adds time to
>	   the allocation of *every* object when it is needed for
>	   only a few objects.
>
>	6) For large objects such as buffers in the megabyte range
>	   initialization time can result in visible delays while
>	   buffers are allocated. For such buffers initialization
>	   is usually not needed.

Back here on planet Earth: operator new DOES CALL THE CONSTRUCTOR for
every array element when allocating an array of objects.  In C++ Ver. 2.0,
it was not possible to call operator new on a class that didn't have a
constructor with no arguments. I believe this has been relaxed in 2.1 --
a constructor with default arguments is called.

>
>	7) In addition to global operator new an objects operator new can
>	   be overloaded to initialize the memory if needed
>

Yes and no. (Mostly no.) Both for non-class types and for ARRAYS OF CLASS 
TYPES, the global ::operator new is called. While it can be changed, that is
not a good idea (ARM p.60) as a general purpose strategy.

>In summary it is my opinion (not that my opinion counts) that initialization
>of object upon allocation is of dubious benefit, and so is a waste of time
>and possibly code. I would prefer to see the spec remain the same. ANSI, are
>you listening?
>--
I mostly care about arrays here. (I rarely do a char* p = new char;) Arrays
of OBJECTS are initialized through a default constructor. You might get ANSI
to rescind that, but I doubt it. My suggestion is to have the same safety
when allocating arrays of non-class type. It is just fine with me if 
the initialization is restricted to arrays only, i.e. int* a=new int[100]
zeroes them out, but int* a = new int; doesn't. It would allow the efficiency
fanatics to get that single int allocated with stupendous speed. 

I really don't envy the ANSI people. I thought that my suggestion of initia-
lizing arrays of non-class type obtained from ::operator new was the most
harmless and innocuous suggestion. It breaks absolutely no old code. But
I got more HATE MAIL about it than about the lvalue/rvalue operator[]
stuff which, if adopted, would actually break code. 

Let me put this in perspective. If you want to allocate an array of 100
ints or pointers and for some reason don't want them initialized with 
zeroes, you can always use malloc. But if I want to write a template which
allocates an array of X (maybe a class, maybe a basic type or a pointer),
I cannot (at least with the ARM syntax) ask the template whether X is a class
and either call new X[...] or calloc( sizeof(X)*... ). 

Cay

jbuck@galileo.berkeley.edu (Joe Buck) (03/19/91)

In article <1991Mar14.042611.14921@mathcs.sjsu.edu>, horstman@mathcs.sjsu.edu (Cay Horstmann) writes:
|> I repeat my request that operator new should default to initializing the
|> memory with the logical 0 value for the type allocated (almost always an
|> all-0 bit pattern, but then who knows how 0 pointers or 0.0 floats are
|> represented on some crazy systems.) ANSI, are you listening?

How are you going to implement this?  operator new is handed a size_t
object and returns an object of type void.  It doesn't know what type
it's supposed to return.  Or do you want to make the "default" operator
new special (preventing a user from writing something similar)?

Even if you could solve the technical problems, I'm still against it;
it will just lead to lazy programming and subtle bugs (people will
stop worrying about initializing every object member).

Next you'll be asking for a guarantee that when I write

void foo (int arg1) {
	char byteArray[BIGBUF];
	int intArray[INTBUF];
	...
}

that byteArray and intArray be initialized to all zeros as well.  If not,
why not?  Why should creating an array with new be different from making
automatic variables?

--
Joe Buck
jbuck@galileo.berkeley.edu	 {uunet,ucbvax}!galileo.berkeley.edu!jbuck	

tom@elan.Elan.COM (Thomas Smith) (03/20/91)

horstman@mathcs.sjsu.edu (Cay Horstmann):
> In article <184@heurikon.heurikon.com> daves@ex.heurikon.com (Dave Scidmore) writes:
>>In article <1991Mar14.042611.14921@mathcs.sjsu.edu> horstman@mathcs.sjsu.edu (Cay Horstmann) writes:
>>>
>>>I repeat my request that operator new should default to initializing the
>>>memory with the logical 0 value for the type allocated (almost always an
>>>all-0 bit pattern, but then who knows how 0 pointers or 0.0 floats are
>>>represented on some crazy systems.) ANSI, are you listening?
>>
>>I think that *not* zeroing out memory should be the default. My reasons are
>>as follows: 
>>
>>	1) Zeroing is infrequently needed and seldom even helpful.
> 
> Huh? When you say X** a = new X*[100], isn't it most likely that you want
> all those X*'s to be null pointers?

No.  You're array might be null-terminated - in other words, you might do
    X** a = new X*[10000];	// notice the extra zeros
    a[0] = 0;			// initialy empty - null first object
The extra effort supplied by the compiler second-guessing what I the
programmer intended to do is wasted effort.  Furthermore, you may be
allocating the array to be large enough to handle a possible extreme case
in your program, rather than normal cases, thus it may need to be much
larger than 100.  Zeroing out 10s or 100s of thousands of bytes is not
a trivial operation efficiency-wise.

> I really don't envy the ANSI people. I thought that my suggestion of initia-
> lizing arrays of non-class type obtained from ::operator new was the most
> harmless and innocuous suggestion. It breaks absolutely no old code.

For those of us actually developing products, "breaking code" is read as
"taking a program with a certain behavior and changing it for the worse".
Slowing down a program a perceptable amount by doing something beyond
the control of the programmer certainly meets this description.

> Let me put this in perspective. If you want to allocate an array of 100
> ints or pointers and for some reason don't want them initialized with 
> zeroes, you can always use malloc. But if I want to write a template which
> allocates an array of X (maybe a class, maybe a basic type or a pointer),
> I cannot (at least with the ARM syntax) ask the template whether X is a class
> and either call new X[...] or calloc( sizeof(X)*... ). 

But you also said earlier
> I was talking about new applied to NON-CLASS TYPES. They don't have
> a constructor.

In other words, there isn't any benefit in initializing objects
that were due to be constructed (or possibly not), because that would be
wasted effort.  Your "template" example above contradicts this.
Instead of adding wasted overhead for many legitimate algorithms, you should
treat your specific case in its specific manner.  If you want your memory
initialized, then initialize it.

If the language cannot descriminate between your useful initialization
scenario and one that is detrimental in another case, then the language
has to take the least common denominator.

    Thomas Smith
    Elan Computer Group, Inc.
    (415) 964-2200
    tom@elan.com, ...!{ames, uunet, hplabs}!elan!tom

jadam@cs.tamu.edu (James P Adam) (03/20/91)

Newsgroups: comp.lang.c++
Subject:  Friend Functions versus Friend Classes
Summary: protected vs private
Expires: 
References: <1991Mar16.172814.6525@mathcs.sjsu.edu> <966@elan.Elan.COM>
Sender:   
Followup-To: 
Distribution: 
Organization: Computer Science Department, Texas A&M University
Keywords: 

>I have a question about friend functions.  
> [stuff deleted]
>class ToDoList {
>  friend Boolean Manager::Reprioritize(Bug& item, int priority);
>  private:
>     ThingList *things;
>};
>
>class InternalPerson {
>private:
>    ToDoList ToDo;
>};
>
>class Manager : public InternalPerson {
>public:
>  Boolean Reprioritize(Bug& item, int priority); // needs to look at ToDoList
>};

   It's hard to tell from this outline what exactly is going on
inside the Reprioritize function (which is where the problem is,
I assume).  If you're trying to do something with the ToDoList "ToDo"
that is declared in class InternalPerson, recognize that you can't
access the information in a InternalPerson::ToDo directly from class
Manager, since ToDo is declared "private" inside InternalPerson.  If
you want access to an InternalPerson::ToDo variable from class
Manager, try making ToDo "protected" inside Internal person, instead
of private.
   If this answer is off track, My Humble Appologies (MHA).  If
you wind up not getting the answer you want in the next day or so,
you might consider posting a larger snippet of your code, esp. the code 
inside the function that is giving you the problems, plus the actual
error/warning messages from the compiler.
     Jim

jbuck@galileo.berkeley.edu (Joe Buck) (03/21/91)

In article <1991Mar16.172814.6525@mathcs.sjsu.edu>, horstman@mathcs.sjsu.edu (Cay Horstmann) writes:
|> In article <184@heurikon.heurikon.com> daves@ex.heurikon.com (Dave Scidmore) writes:
|> >	1) Zeroing is infrequently needed and seldom even helpful.
|> 
|> Huh? When you say X** a = new X*[100], isn't it most likely that you want
|> all those X*'s to be null pointers?

What about when you say

void func() {
	X* arrayOfPointers[100];
	...
}

Wouldn't you want the pointers to be initialized in this case as
well?  What you're really proposing sounds like specifying a
default constructor for non-class types (i.e. pointers get 0,
doubles get 0.0, chars get '\0', etc).  This has some advantages,
but I would hope there'd be a way of turning it off for cases where
it's wasteful.


--
Joe Buck
jbuck@galileo.berkeley.edu	 {uunet,ucbvax}!galileo.berkeley.edu!jbuck	

horstman@mathcs.sjsu.edu (Cay Horstmann) (03/22/91)

In article <966@elan.Elan.COM> tom@elan.Elan.COM (Thomas Smith) writes:
>>>
>>>	1) Zeroing is infrequently needed and seldom even helpful.
>> 
>> Huh? When you say X** a = new X*[100], isn't it most likely that you want
>> all those X*'s to be null pointers?
>
>No.  You're array might be null-terminated - in other words, you might do
>    X** a = new X*[10000];	// notice the extra zeros
>    a[0] = 0;			// initialy empty - null first object
>The extra effort supplied by the compiler second-guessing what I the
>programmer intended to do is wasted effort.  Furthermore, you may be
>allocating the array to be large enough to handle a possible extreme case
>in your program, rather than normal cases, thus it may need to be much
>larger than 100.  Zeroing out 10s or 100s of thousands of bytes is not
>a trivial operation efficiency-wise.
>
This is an extremely rare case. In C++, it is not at all common to allocate
such a large array right away just to handle a possible extreme case.

It is much smarter to start out with a smaller array and grow it as needed
with a variable array class. 

If you must allocate such a large array, and the penalty for zeroing it
out is unacceptable, you can call malloc. 

To inject a little more realism into the discussion: Most processors have
instructions that can zero out a memory block extremely quickly. But if
you have lots of large blocks of memory "just in case", your program is
much more likely to have to page them out, which is a zillion times more
expensive. 

I continue to propose that operator new zero out arrays of non-class type,
and that programmers who find that unacceptable use malloc. 

Cay

horstman@mathcs.sjsu.edu (Cay Horstmann) (03/22/91)

In article <12194@pasteur.Berkeley.EDU> jbuck@galileo.berkeley.edu (Joe Buck) writes:
>In article <1991Mar16.172814.6525@mathcs.sjsu.edu>, horstman@mathcs.sjsu.edu (Cay Horstmann) writes:
>|> In article <184@heurikon.heurikon.com> daves@ex.heurikon.com (Dave Scidmore) writes:
>|> >	1) Zeroing is infrequently needed and seldom even helpful.
>|> 
>|> Huh? When you say X** a = new X*[100], isn't it most likely that you want
>|> all those X*'s to be null pointers?
>
>What about when you say
>
>void func() {
>	X* arrayOfPointers[100];
>	...
>}
>
>Wouldn't you want the pointers to be initialized in this case as
>well?  What you're really proposing sounds like specifying a
>default constructor for non-class types (i.e. pointers get 0,
>doubles get 0.0, chars get '\0', etc).  This has some advantages,
>but I would hope there'd be a way of turning it off for cases where
>it's wasteful.
>
>
Joe, I wouldn't argue against that but I am not about to propose it myself.
I like to live in peace. 

There is a reason why I am asking that operator new initialize arrays. If you
write a template class for variable size arrays (of ints, char*, X,...)
it would be desirable to rely on initialization in all cases since there is
(at least with the current template syntax) no way of differentiating 
between class- and non-class types ("#if isclass(X)...")

But in the case of a fixed array inside a single class, I guess one can
have that class's constructor do the initialization. 

Cay

daves@ex.heurikon.com (Dave Scidmore) (03/22/91)

(Cay Horstmann) writes:
>It is much smarter to start out with a smaller array and grow it as needed
>with a variable array class. 

Not if the array could get very large as the copying of the old small array
to the new large array can get extreemely expensive.

>If you must allocate such a large array, and the penalty for zeroing it
>out is unacceptable, you can call malloc. 

And if the zeroing of the array is mandatory, you can simply clear it after
allocating it (which my original contention is won't be required often.)

>To inject a little more realism into the discussion: Most processors have
>instructions that can zero out a memory block extremely quickly. But if
>you have lots of large blocks of memory "just in case", your program is
>much more likely to have to page them out, which is a zillion times more
>expensive. 

Assuming it is not a imbeded processor or a dedicated application which does
not have a paging operating system to run under.

>I continue to propose that operator new zero out arrays of non-class type,
>and that programmers who find that unacceptable use malloc. 

One thing that occurred to me recently is that the proposal to zero memory
on array allocation of built in types is inconsistent with the way class
objects behave. Class objects can only call a constructor if one exists for
the class being arrayed. This is to ensure that an array of class objects
is initialized that same way an individual object of the same class would
be. Built in types are not cleared upon allocation and in that sense they
are similar to class objects with no constructor. Therefore an array of
built in types should not be cleared since this is exactly the opposite
of what happens when you only allocate a single built in type. The rules
regarding calling the constructor for arrays of class objects were designed
to provide arrays with class objects that are virtually identical to the
non array ones. Proposing that built in type be cleared when appearing in
an array but not individually does just the opposite. Requiring them to
be cleared in all cases is inconsistent with class objects which are not
cleared when no constructor exists.
--
Dave Scidmore, Heurikon Corp.
dave.scidmore@heurikon.com

gwu@nujoizey.tcs.com (George Wu) (03/23/91)

-
     Concerning the ongoing debate of whether newly allocated objects should
have memory initialized to zero, I propose we make it a compiler command
line option.  This will enable both camps to have the behavior they wish.
(I don't even want to get into an argument over what the compiler default
action should be.  Actually, I do.  The default should be to not initialize
memory on its own.)

     Given this capability, I suspect developers would usually turn on the
zeroing option while an application is under development, and then turn it
off when the code is ready to be tested and shipped.

     Does this fall within the ANSI committee's mandate?  Or is this idea
too implementation oriented for their more language definition role?

							George

----
George J Wu, Software Engineer        | gwu@tcs.com or uunet!tcs!gwu
Teknekron Communications Systems, Inc.| (415) 649-3752
2121 Allston Way, Berkeley, CA, 94704 | Quit reading news.  Get back to work.

horstman@mathcs.sjsu.edu (Cay Horstmann) (03/24/91)

In article <12132@pasteur.Berkeley.EDU> jbuck@galileo.berkeley.edu (Joe Buck) writes:
>In article <1991Mar14.042611.14921@mathcs.sjsu.edu>, horstman@mathcs.sjsu.edu (Cay Horstmann) writes:
>|> I repeat my request that operator new should default to initializing the
>|> memory with the logical 0 value for the type allocated (almost always an
>|> all-0 bit pattern, but then who knows how 0 pointers or 0.0 floats are
>|> represented on some crazy systems.) ANSI, are you listening?
>
>How are you going to implement this?  operator new is handed a size_t
>object and returns an object of type void.  It doesn't know what type
>it's supposed to return.  Or do you want to make the "default" operator
>new special (preventing a user from writing something similar)?

I am not proposing to build this into operator new. Just like arrays of
classes get initialized AFTER operator new is called, arrays of non-class
objects would be initialized afterwards. You could still supply your
own global operator new. 

>
>Even if you could solve the technical problems, I'm still against it;
>it will just lead to lazy programming and subtle bugs (people will
>stop worrying about initializing every object member).

Now I agree it would be AWFUL if people started worrying about initia-
lizing every object member. For that reason, constructors should be BANNED
from the language.

Get real. Automatic initialization is one of the great features of C++. 
People have enough other things to worry about when writing programs.

>
>Next you'll be asking for a guarantee that when I write
>
>void foo (int arg1) {
>	char byteArray[BIGBUF];
>	int intArray[INTBUF];
>	...
>}
>
>that byteArray and intArray be initialized to all zeros as well.  If not,
>why not?  Why should creating an array with new be different from making
>automatic variables?

I am not going to argue this. It is not a problem I often have when pro-
gramming C++. It would be an incompatible change from C. I restrict my
request to operator new which doesn't exist in C, and for which an alter-
native exists (calling malloc) when the cost of zeroing out is considered
excessive. 

Cay

steve@taumet.com (Stephen Clamage) (03/27/91)

gwu@nujoizey.tcs.com (George Wu) writes:

>     Concerning the ongoing debate of whether newly allocated objects should
>have memory initialized to zero, I propose we make it a compiler command
>line option...
>     Does this fall within the ANSI committee's mandate?  Or is this idea
>too implementation oriented for their more language definition role?

The standardization effort cannot address issues such as command-line
options.  Not all compilers have command lines.  "Compilation" might
be distributed among various components of an integrated translation
system.

Taking the wider view, the C++ ANSI committee (X3J16) followed the
lead of the C committee (X3J11) and rejected the idea of "optional
features" or "levels of conformance".

None of this prevents an implementation from providing additional
features which do not conflict with requirements of the standard.
Presumably nothing would prohibit the default 'operator new' from
zeroing memory if an implementor felt this would be considered
a benefit by potential customers.

Personally, I think it would be more beneficial to set memory to
'impossible' values where this concept makes sense on a given
architecture.  Zeroing memory hides too many bugs involving
uninitialized variables.  (Unless zero is an 'impossible' value :-)).
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com