A demo program on class and stuct, Am I right?

Daniel Keep daniel.keep.lists at gmail.com
Sun Jun 18 02:13:22 PDT 2006


I'm going to assume from your subject line that you're looking for
feedback on the program.  Helps to explicitly ask your question in the
message body :)

By the way, the NG sometimes drops indentation, so it helps to stick
"# " before each of your source lines to preserve it.  A minor
annoyance, but it helps reading long code blocks immensely.

Now, let's see...

solotony at sohu.com wrote:
> class TheObject
> {
> int a;
> 
> bool opEquals(TheObject b)
> {
> return true;
> }
> }
> 
> struct TheValue
> {
> int a;
> }
> 
> void demoObj()
> {
> TheObject a, b; //both are ref;

Indeed.

> 
> assert(a is null);  //used be null

Well, it's STILL null, but yes.

> 
> //if( a == b){     //runtime crash here, == is a call to opEqual method.
> //}

Correct.

> 
> a = new TheObject; //heap object, gc equipped.
> b = new TheObject;

Not QUITE true.  There is nothing that says these need to be on the
heap, or managed by the GC.  All that's required is that 'a' and 'b'
point to some valid object in memory somewhere.  HOW you allocate that
memory is up to you.

But other than that, correct :)

> 
> assert (a !is b); //ref to differet object
> assert (a == b);  //the object is equal.
> 

Yup.  Although your opEquals() always return true, the comments are right.

> auto TheObject stackObject = new TheObject; // the only way to create a stack
> object.

Wrong!  'auto' doesn't create the object on the stack.  Or at least, it
currently doesn't: DMD allocates 'auto' objects the same way it
allocates normal objects.  Different implementations are free to
allocate 'auto' objects on the stack or by some other means, but I'm not
aware of any that do.

You can't really think of 'auto' in terms of how or where it allocates
the object: it is explicitly for managing that resultant memory.

The short version: 'stackObject' will be destroyed at the end of scope
come hell or high water.  That's all you can say about it in general.

> 
> TheObject* p;
> 
> assert(p is null);
> 

Again, this is true.  However, it's never a good idea to rely on
side-effects.  If you want 'p' to be null, you should explicitly set it
to 'null'.

This is mostly a stylistic issue, but it does help code readability when
you can say, "Yes, this value is definitely initialized to X" as opposed
to "well, the default SHOULD be X..."

> //p = a; //cannot implicitly convert ref to pointer;
> p = &a; // ok
> p.a = 4;
> assert( a.a == 4); //access successfully
> 
> //b = p; //convert p to ref is illegeal;
> b = *p; //ok
> 
> assert(a is b);  //ok, ref to same object.

This should be right... I don't usually mix pointers and references.  In
this case, remember that what you've got a pointer to is NOT the object
itself, but the REFERENCE to the object.  Hence why you can't "convert"
between them; they're fundamentally different things.

> 
> TheObject* q;
> q = &b;
> 
> //can we call opEquals method through pointer?
> assert(*p == *q);

Well, I can't see why not.  In this case, your code should expand to

# assert( (*p) == (*q) )

Which is just comparing two object instances.

> 
> //and identic? why? see /d/expression.html#EqualExpression
> assert(*p is *q);

Again, this *should* be fine, but I haven't tried this.

As for why: p and q are pointers to references to objects.  *p and *q
are references to objects.  And it makes perfect sense to want to
compare the two to see if they're referencing the same object.

*p == *q would call (*p).opEquals(*q).
*p is *q is like doing a pointer compare.

> 
> q = &a;
> //the pointer value? 
> assert(p == q);
> 
> //and what's the identical comparing mean? /d/expression.html#EqualExpression
> assert(p is q);
> }

In this case, I'm not sure what 'p is q' is doing.  'is' is used to test
two references to make sure they point to the same thing... this
expression is like using 'is' on two integers; it doesn't really make
any sense.

> void demoValue()
> {
> TheValue v; //on stack?
> v.a = 4;    //yes, on stack;

TheValue is just a struct so, yes, it gets allocated on the stack in
*this* case.

> //v = new TheValue; //no, v is a value, new TheValue is a pointer(ref?)
> v = *new TheValue;  //ok. temporary copy and assign?

I'm not sure what "temporary copy and assign" means.

TheValue is a struct, which are deal with as chunks of memory (whilst
objects are usually handled via references).  What you're doing here is
the same as this:

# v = *(new TheValue);

Which means "allocate a new TheValue on the GC heap", "dereference this
pointer" and then "copy the value from the RHS to the LHS".

The GC will eventually clean up the lost reference to your temporary
TheValue you allocated.

> //auto TheValue v1 = new TheValue; //can't be auto value.
> TheValue v1 = v;

Correct.

> assert( v1 == v);  //call to opEquals
> assert( v1 is v);  //why this ? see /d/expression.html#EqualExpression

Again, using 'is' in this case makes no sense: v1 and v are values, not
reference types.

> TheValue *p;
> p = new TheValue; //on heep and gc?

Yes, the memory pointed to by p is on the GC's heap.

> assert(*p == v); 
> 
> //no different between obj ptr and value ptr ?

In this case, you're comparing two values.  v is NOT a pointer: it's the
complete value of the struct.  If you were to pass v to a function, it
would copy the entire structure to the function, not just pass a
reference to it.

In this case, the expression is the same as '(*p) == v' where {*p) is of
type 'TheValue'.  So you're comparing two TheValue structs by value.

I hope I've managed to answer some of your questions, and please forgive
any mistakes I may have made.  The above is correct to the best of my
knowledge.

	-- Daniel

-- 
Unlike Knuth, I have neither proven or tried the above; it may not even
make sense.

v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D
i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP  http://hackerkey.com/



More information about the Digitalmars-d-learn mailing list