[comp.lang.c++] overloading operator new

david@june.cs.washington.edu (David Callahan) (10/05/88)

Stroustrup lists the "new" operator as one that can be
overloaded. I'm not exactly sure what functionality this
provides (over assigning into "this" in the constructor)
and I know I can't get the syntax right. Could someone
show me an example of "new" being overloaded and how
it would be used?

Thanks in advance,
david callahan

mball@cod.NOSC.MIL (Michael S. Ball) (10/05/88)

In article <5949@june.cs.washington.edu> david@uw-june.UUCP (David Callahan) writes:
>Stroustrup lists the "new" operator as one that can be
>overloaded. I'm not exactly sure what functionality this
>provides (over assigning into "this" in the constructor)
>and I know I can't get the syntax right. Could someone
>show me an example of "new" being overloaded and how
>it would be used?

As far as I know, the feature is documented only in the "Evolution of C++"
paper in the Santa Fe workshop proceedings.  The syntax is simple:

class foo {
    :
    :
  void * operator new(long);
    :
};

Your version of cfront may not accept it, however, as it is a recent addition
to the language.

It adds no new functionality over assignment to this, but is less error-prone
and puts all of the allocation code in one place, rather than replicated
in each constructor.  Assignment to "this" has a number of traps into which
one may fall.  For example, you must make sure that there is an assignment
to this on all possible paths through the constructor.  Otherwise, member
constructors may not be called.  Overloading "operator new" seems much cleaner.

A side effect is that the resulting code will probably be better since the
member and base class initializations do not have to be replicated as they
do when "this" is assigned to.

Mike Ball
TauMetric Corporation
1094 Cudahy Pl. Ste 302
San Diego, CA 92110
(619)275-6381

scs@itivax.UUCP (Steve C. Simmons) (10/06/88)

In article <5949@june.cs.washington.edu> david@uw-june.UUCP (David Callahan) writes:
>Could someone show me an example of "new" being overloaded and how
>it would be used?

Someone else has already posted how to do it.  I have no examples,
but can think of a good reason to do it -- exception handling.  Since
new allocates memory, there must be a way of doing garbage collection
should that allocation become unneeded due to an exception.  By overloading
new, you can go a long way to providing your own garbage collection
software and make use of more c-style exception processing.  Not perfect,
but a good step.

-- 
Steve Simmons		...!umix!itivax!scs
Industrial Technology Institute, Ann Arbor, MI.
"You can't get here from here."

keith@nih-csl.UUCP (keith gorlen) (10/08/88)

In article <294@itivax.UUCP>, scs@itivax.UUCP (Steve C. Simmons) writes:
-> In article <5949@june.cs.washington.edu> david@uw-june.UUCP (David Callahan) writes:
-> >Could someone show me an example of "new" being overloaded and how
-> >it would be used?
-> 
-> Someone else has already posted how to do it.  I have no examples,
-> but can think of a good reason to do it -- exception handling.  Since
-> new allocates memory, there must be a way of doing garbage collection
-> should that allocation become unneeded due to an exception.  By overloading
-> new, you can go a long way to providing your own garbage collection
-> software and make use of more c-style exception processing.  Not perfect,
-> but a good step.

I don't see what operator new() has to do with exception handling in C++.  The main
problem with trying to do exception handling in C++ is that there doesn't seem to
be a good way to get the destructors called for auto objects that go out of scope
when an exception is raised.  operator new() is only used when allocating objects
on the free store with new, not when they are auto.  Could you please explain?
Thanks.

-- 
	Keith Gorlen			phone: (301) 496-5363
	Building 12A, Room 2017		uucp: uunet!nih-csl!keith
	National Institutes of Health	Internet: keith%nih-csl@ncifcrf.gov
	Bethesda, MD 20892

scs@itivax.UUCP (Steve C. Simmons) (10/09/88)

In article <797@nih-csl.UUCP> keith@nih-csl.UUCP (keith gorlen) writes:
-In article <294@itivax.UUCP>, scs@itivax.UUCP (Steve C. Simmons) writes:
--> In article <5949@june.cs.washington.edu> david@uw-june.UUCP (David Callahan) writes:
--> >Could someone show me an example of "new" being overloaded and how
--> >it would be used?
--> 
--> Someone else has already posted how to do it.  I have no examples,
--> but can think of a good reason to do it -- exception handling.  Since
--> new allocates memory, there must be a way of doing garbage collection
--> should that allocation become unneeded due to an exception.  By overloading
--> new, you can go a long way to providing your own garbage collection
--> software and make use of more c-style exception processing.  Not perfect,
--> but a good step.
-
-I don't see what operator new() has to do with exception handling in C++.
-The main problem with trying to do exception handling in C++ is that there
-doesn't seem to be a good way to get the destructors called for auto
-objects that go out of scope when an exception is raised.  operator new()
-is only used when allocating objects on the free store with new, not when
-they are auto.  Could you please explain?

Exactly correct.  To use this solution, one has to either (a) use only
static objects or those explicitly created with new(), or (b) overload
the creator/destructor functions to use your garbage-collectable new().
Or a combination of the two.  It's not a real elegant solution, but it'd
probably work.
-- 
Steve Simmons		...!umix!itivax!scs
Industrial Technology Institute, Ann Arbor, MI.
"You can't get here from here."

shap@polya.Stanford.EDU (Jonathan S. Shapiro) (10/10/88)

In article <298@itivax.UUCP> scs@itivax.UUCP (Steve C. Simmons) writes:
>In article <797@nih-csl.UUCP> keith@nih-csl.UUCP (keith gorlen) writes:
>-In article <294@itivax.UUCP>, scs@itivax.UUCP (Steve C. Simmons) writes:
>-
>-I don't see what operator new() has to do with exception handling in C++.
>-The main problem with trying to do exception handling in C++ is that there
>-doesn't seem to be a good way to get the destructors called for auto
>-objects that go out of scope when an exception is raised.  operator new()
>-is only used when allocating objects on the free store with new, not when
>-they are auto.  Could you please explain?
>
>Exactly correct.  To use this solution, one has to either (a) use only
>static objects or those explicitly created with new(), or (b) overload
>the creator/destructor functions to use your garbage-collectable new().
>Or a combination of the two.  It's not a real elegant solution, but it'd
>probably work.

There is at least one way to do exception handling in the current
scheme of things.  It goes like this:

Exception handlers define a scope. Thus, we logically think about
instantiating the "catch" for the exception handling (in LISP terms)
and that the catch goes out of scope at some time in the future.
Within the scope of the "catch", the exception mechanism is active.

Think of the heap as a temporally scoped object, where the
instantiation of a "catch" scope logically partitions the heap into
stuff older than that catch and stuff newer than that catch.

Now overload all instances of New() within that scope so that the
run-time system maintains, along with the scope information, a spare
pointer to every object allocated with New() within that scope, along
with a pointer to the destructor function.  Thus, associated with each
heap scope we have a list of objects and their destructors.

When an object is destroyed, it's pointer pair is removed from the
list by the global delete() operator.

Now, when an error is raised or a "throw" is executed, we locate the
scope that is thrown to and destroy all of the stack-instantiated
objects. We then destroy dynamically allocated things in the clobbered
scopes in an undefined order.

There is [at least] one problem with this, which is that it is
possible to call a dynamic delete() on an object that has already been
deleted() by the recovery mechanism. This should be considered not to
be an error within the context of the recovery. The heap-scope oblist
can be used to verify these cases.

Now I know that there are lots and lots of problems here.  I also know
that I don't know a lot about exception handling.  Can someone give me
a non-flaming list of problems with this idea so that I can think on it
further?  The big problem I see is that there is no good ordering
constraint on the destructions.


Jon

schmidt@crimee.ics.uci.edu (Doug Schmidt) (06/14/90)

Both cfront and g++ fail to compile the following code:

----------------------------------------
#include <stddef.h>
class Foo
{
public:
  Foo () {;}
  void *operator new (size_t, int);
  void operator delete (void *);
};
----------------------------------------

cfront sez:

----------------------------------------
"t.c", line 3: error:  argument  2 of type int  expected for
Foo::operator new()
----------------------------------------

g++ sez:

----------------------------------------
t.c: In method Foo::Foo ():
t.c:5: too few arguments for method `operator new'
----------------------------------------

However, both accept:

----------------------------------------
#include <stddef.h>
class Foo
{
public:
  Foo () {;}
  void *operator new (size_t, int = 0);
                              //  ^^^ note default arg
  void operator delete (void *);
};
----------------------------------------

Is there some reason for this restriction (i.e., that a one argument
version of class-specific operator new must exist in the class decl if
any other form of class-specific operator new is declared)?

thanks,

  Doug
--
Any man's death diminishes me,              | schmidt@ics.uci.edu (ARPA)
Because I am involved in Mankind;           | office: (714) 856-4043
And therefore never send to know for whom the bell tolls;
It tolls for thee        -- John Donne

landauer@morocco.Sun.COM (Doug Landauer) (06/15/90)

> Is there some reason for this restriction (i.e., that a one argument
> version of class-specific operator new must exist in the class decl if
> any other form of class-specific operator new is declared)?

Upon entry to Foo's constructor, if "this" is zero, Foo's constructor
will (secretly) allocate space for Foo, by calling Foo's operator new.
(At least that's how cfront does it -- I can't find a reference-manual
citation that requires this.)  It only knows how to call a standard
one-argument version -- there is no way for it to guess what value(s)
to provide for any other arguments.

So why doesn't it just use the global (non-class-specific) one?
Because of the "no overloading across different scopes" rule.  See
section 13.1 ("Declaration Matching") of the 2.1 reference manual (or
Bjarne & Ellis's new book) for the details & rationale.
-- 
Doug Landauer - Sun Microsystems, Inc. - Languages - landauer@eng.sun.com
    Matt Groening on C++:  "Our language is one great salad."

wmmiller@cup.portal.com (William Michael Miller) (06/16/90)

landauer@morocco.Sun.COM (Doug Landauer) writes:
> Foo's constructor will (secretly) allocate space for Foo...It only knows
> how to call a standard one-argument version

This implementation is problematic.  In fact, the only logical reason
requiring constructors to handle allocation, instead of the implementation
calling operator new() outside the constructor and passing the result in as
the value of "this," is the desire to support the obsolete practice of
assignment to "this."  In the language as currently defined, it ought to be
possible to prohibit use of ordinary "new" (as opposed to use of the
overloaded, "placement" syntax) by specifying only an overloaded operator
new() in the class; this implementation prevents use of this desirable
capability.

What I would propose is to prohibit assignment to "this," even in
implementations that currently support it for compatibility with old code,
in any constructor of a class that contains (not inherits but contains
directly) a declaration of *any* form of operator new().  This would permit
the compiler to do away with the implicit check for 0 and call of operator
new() for such classes and to flag as an error any attempt to say "new
classname" on a class for which no "operator new(size_t)" is visible.

(In other words, I think the cited behavior is, or at least very soon ought
to be defined as, a bug.)

------------------------------------------------------------------------------
William M. Miller, Glockenspiel, Inc.; P. O. Box 366, Sudbury, MA 01776-0003
wmmiller@cup.portal.com         BIX: wmiller            CI$: 72105,1744