dmg@ssc-vax.UUCP (David Geary) (05/31/89)
According to BS, section 5.5.7, a constructor for a class can determine whether it was called by new or not. "If it is called by new, the pointer this has the value zero at entry, otherwise this points to space already allocated for the object..." Ok, so what does the following print? #include <stdio.h> class testclass { public: testclass() { if(this == 0) puts("Used new..."); else puts("Did not use new..."); } ~testclass() { puts("I'm a destructor..."); } }; main() { testclass var; new testclass; } Output: Did not use new... Did not use new... I'm a destructor... This tells me one of two things: 1) I've found a bug in the compiler. 2) I don't know what the h*ll I'm doing. My ego tells me #1, but my experience tells me it has to be #2 ;-) -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~ David Geary, Boeing Aerospace, Seattle ~ ~ "I wish I lived where it *only* rains 364 days a year" ~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dld@F.GP.CS.CMU.EDU (David Detlefs) (05/31/89)
Dave Geary asks why this program: #include <stdio.h> >class testclass >{ > public: > > testclass() { if(this == 0) puts("Used new..."); else puts("Did not use new..."); } > ~testclass() { puts("I'm a destructor..."); } >}; > >main() >{ > testclass var; > new testclass; >} produces this output: >Did not use new... >Did not use new... >I'm a destructor... I believe I can explain this. Look at 'main.' The first line of the output is caused by the constructor call to initialize 'var', a stack-allocated automatic variable. The second line is caused by the evaluation of the expression 'new testclass;' This *does* use new, so why does it say it doesn't? Well if you look at testclass, you'll find that sizeof(testclass) is 0. I would guess that the 'malloc' that operator new is calling returns 0 when it is asked to allocate a zero-sized object. Thus, 'this' is 0 on entry to the constructor. Finally, the testclass destructor is called when 'var' goes out of scope. Hope this helps. Dave -- Dave Detlefs Any correlation between my employer's opinion Carnegie-Mellon CS and my own is statistical rather than causal, dld@cs.cmu.edu except in those cases where I have helped to form my employer's opinion. (Null disclaimer.) --
leo@atcmp.nl (Leo Willems) (06/02/89)
> >Dave Geary asks why this program: > > >>class testclass >>{ >> public: >> >> testclass() { if(this == 0) puts("Used new..."); else puts("Did not use new..."); } >> ~testclass() { puts("I'm a destructor..."); } >>}; >> >>main() >>{ >> testclass var; >> new testclass; >>} > >produces this output: > >>Did not use new... >>Did not use new... >>I'm a destructor... In the paper `the evolution of C++ 1985 to 1987' Bjarne Stroustrup gives a more detailed example of the way how to use the -this- pointer in a constructor when allocating memory yourself. (versus par. 5.5.7 in the C++ P.L.) Somewhere (I can't find it right now) it is mentioned that the assignment to the -this- pointer in the constructor should be made on every possible execution path. The following code does not suffer from the problem above: extern char*malloc(int); extern void free(char*); class testclass { private: int used_new; public: testclass(); ~testclass(){ if (used_new){ free((char*)this); this = 0; // this assignment must be done } puts("I'm a destructor..."); } }; testclass::testclass() { if (this == 0){ puts("Used new..."); this = (testclass*) malloc(sizeof(testclass)); // this assignment must be done used_new = 1; //assigment after allocation! } else { used_new = 0; puts("Did not use new..."); this = this; // this assignment must be done } } main() { testclass var; new testclass; } This solution leaves me with a question too. Shouldn't the destructor also assign on every possible path to the -this- pointer? Leo Willems Internet: leo@atcmp.nl AT Computing UUCP: mcvax!hp4nl!kunivv1!atcmpe!leo P. O. Box 1428 6501 BK Nijmegen The Netherlands
wmm@sdti.SDTI.COM (William M. Miller) (06/02/89)
In article <2684@ssc-vax.UUCP> dmg@ssc-vax.UUCP (David Geary) writes: > According to BS, section 5.5.7, a constructor for a class can determine whether >it was called by new or not. That only works if the constructor assigns to `this.' (That's the context of the statement in 5.5.7 you mention, although the connection is not as clear as it ought to be.) What happens is that, if there is an assignment to `this' in the body of the constructor, the value of `this' is left as it is upon entry until that assignment occurs: zero if allocated via `new,' nonzero for static and auto. If there is no assignment to `this,' the compiler inserts code at the beginning of the constructor, before any of the statements in the body, to check if `this' is zero and do the allocation via operator new() if needed. The allocation and assignment to `this' have already occurred before the test in your example constructor. This question illustrates the reason assignment to `this' is replaced in version 2.0: it's confusing, unclear, error-prone, etc.
kt@msor.UUCP (Keith Tizzard) (06/02/89)
In article <2684@ssc-vax.UUCP> dmg@ssc-vax.UUCP (David Geary) writes:
:
: According to BS, section 5.5.7, a constructor for a class can determine whether
:it was called by new or not.
:
:"If it is called by new, the pointer this has the value zero at entry,
:otherwise this points to space already allocated for the object..."
:
: Ok, so what does the following print?
:
:#include <stdio.h>
:
:class testclass
:{
: public:
:
: testclass() { if(this == 0) puts("Used new..."); else puts("Did not use new..."); }
: ~testclass() { puts("I'm a destructor..."); }
:};
:
:main()
:{
: testclass var;
: new testclass;
:}
:
:Output:
:
:Did not use new...
:Did not use new...
:I'm a destructor...
:
: This tells me one of two things:
:
: 1) I've found a bug in the compiler.
: 2) I don't know what the h*ll I'm doing.
:
: My ego tells me #1, but my experience tells me it has to be #2 ;-)
:
:--
:~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:~ David Geary, Boeing Aerospace, Seattle ~
:~ "I wish I lived where it *only* rains 364 days a year" ~
:~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Zortech C++ produces the following output:-
Used new...
Used new...
I'm a destructor...
: From: dld@F.GP.CS.CMU.EDU (David Detlefs)
: References: <2684@ssc-vax.UUCP>
:
:
: And in <2684@ssc-vax.UUCP> David Detlefs adds :
:
:
: I believe I can explain this. Look at 'main.' The first line of the
: output is caused by the constructor call to initialize 'var', a
: stack-allocated automatic variable. The second line is caused by the
: evaluation of the expression 'new testclass;' This *does* use new, so
: why does it say it doesn't? Well if you look at testclass, you'll
: find that sizeof(testclass) is 0. I would guess that the 'malloc' that
: operator new is calling returns 0 when it is asked to allocate a
: zero-sized object. Thus, 'this' is 0 on entry to the constructor.
: Finally, the testclass destructor is called when 'var' goes out of
: scope.
So I added an integer in the private part of the class and Zortech
then produced:
Did not use new...
Did not use new...
I'm a destructor...
So where does this get us? :-)
vasta@apollo.COM (John Vasta) (06/03/89)
In article <2684@ssc-vax.UUCP> dmg@ssc-vax.UUCP (David Geary) writes: > > According to BS, section 5.5.7, a constructor for a class can determine whether >it was called by new or not. > >"If it is called by new, the pointer this has the value zero at entry, >otherwise this points to space already allocated for the object..." > > Ok, so what does the following print? > >#include <stdio.h> > >class testclass >{ > public: > > testclass() { if(this == 0) puts("Used new..."); else puts("Did not use new..."); } > ~testclass() { puts("I'm a destructor..."); } >}; > >main() >{ > testclass var; > new testclass; >} > >Output: > >Did not use new... >Did not use new... >I'm a destructor... > > This tells me one of two things: > > 1) I've found a bug in the compiler. > 2) I don't know what the h*ll I'm doing. > > My ego tells me #1, but my experience tells me it has to be #2 ;-) > >-- >~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ >~ David Geary, Boeing Aerospace, Seattle ~ >~ "I wish I lived where it *only* rains 364 days a year" ~ >~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Checking the value of 'this' only makes sense if you want to assign to it. The statement from The Book is in the section about taking over the storage allocation mechanism; the first sentence in 5.5.7 is "When assigning to this in a constructor, the value of this is undefined until that assignment." If you don't assign to this, the compiler synthesizes code to do so (if this == 0). The code is inserted at the beginning of the constructor, so the first statements you write are guaranteed to never see this == 0, unless you assign to this somewhere, or there's some sort of storage allocation failure. If you change the constructor to read: testclass() { if(this == 0) puts("Used new..."); else puts("Did not use new..."); this = this; } then the output from the program is: Did not use new... Used new... I'm a destructor... -- John Vasta Apollo Computer, Inc. vasta@apollo.com M.S. CHA-01-LT (508) 256-6600 x6362 330 Billerica Road, Chelmsford, MA 01824 UUCP: {decwrl!decvax, mit-eddie, attunix}!apollo!vasta
ttwang@polyslo.CalPoly.EDU (Thomas Wang) (06/03/89)
In article <363@msor0.UUCP> kt@msor.UUCP (Keith Tizzard) writes: >According to BS, section 5.5.7, a constructor for a class can determine whether >it was called by new or not. >"If it is called by new, the pointer this has the value zero at entry, >otherwise this points to space already allocated for the object..." >#include <stdio.h> >class testclass >{ public: >testclass() { if(this == 0) puts("Used new..."); else puts("Did not use new..."); } > ~testclass() { puts("I'm a destructor..."); } >}; >main() { > testclass var; > new testclass; } Testing (this == 0) only works if you set 'this' to some value inside the constructor. I have a non-portable hack though. testclass::testclass() { int dummy; if (this < &dummy) puts("Used new\n"); else puts("did not use new\n"); } This hack depends on the fact that stack and heap usually grows into each other from opposite side of memory. -Thomas Wang (Mak-Kuro Kurosuke, come on out! If you don't come out, we'll pull your eyeballs out! - as heard in Tonari No Totoro ) ttwang@polyslo.calpoly.edu
fredriks@kuling.UUCP (Fredrik Stax{ng) (06/04/89)
I also had this problem when I tried to implement reference counting. Because I wanted the class to be derivable I couldn't use the malloc hack (and did not want to), but changed the new() function to set the pointer new_last to the last new'ed object. I think there should be a defined way of doing this. I also encountered another problem. I wanted to get the pointer class to behave as a native pointer, but I didn't manage to get -> operator working. If the compiler had recognized the equivalence a->b <=> (*a).b this had been easy. -- Fredrik Stax{ng | C looks like a mix of Algol and TECO. CS Student@Uppsala University | -- KPJ Jaakkola fredriks@kuling.docs.uu.se |
pj@hrc63.co.uk (Mr P Johnson "Baddow") (06/26/89)
In article <43984c6e.1ad5a@apollo.COM>, vasta@apollo.COM (John Vasta) writes: > > Checking the value of 'this' only makes sense if you want to assign to it. > The statement from The Book is in the section about taking over the storage > allocation mechanism; the first sentence in 5.5.7 is > > "When assigning to this in a constructor, the value of this is undefined > until that assignment." Thats in The Book, but Stroustrup has written "The Evolution of C++" which describes member operator functions for new and delete which do this sort of think much more neatly. At least one compiler (Oregon) now does it this way. -- Paul Johnson, | `The moving finger writes, And having writ, moves on,' GEC-Marconi Research | Omar Kyham when contemplating `vi'. ------------------------------------------------------------------------------ The company has put a radio inside my head: it controls everything I say!