Thread overview
A demo program on class and stuct, Am I right?
Jun 18, 2006
solotony
Jun 18, 2006
Daniel Keep
Jun 19, 2006
solotony
June 18, 2006

class TheObject
{
int a;

bool opEquals(TheObject b)
{
return true;
}
}

struct TheValue
{
int a;
}

void demoObj()
{
TheObject a, b; //both are ref;

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

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

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

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

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


TheObject* p;

assert(p is null);

//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.

TheObject* q;
q = &b;

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

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

q = &a;
//the pointer value?
assert(p == q);

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

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

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

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

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

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

assert(*p == v);

//no different between obj ptr and value ptr ?

}


int main()
{
demoObj();
demoValue();
return 0;
}


June 18, 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@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/
June 19, 2006
Thanks very much! you're so kind and patient.