On Friday, 24 July 2015 at 18:55:26 UTC, Frank Pagliughi wrote:
So then, of course, I hope/wonder/assume that the pointer to
the heap is sufficient to keep the heap memory alive, and that
this would be OK from the GC perspective to do something like
this:
B* make_b_thing(int i) { cast(B*) new B(i); }
(You missed a return there.)
I haven't followed the discussion, so I may be missing the point
here. But if you're doing this so that the GC is aware of the
`new`ed B, then you really don't need to. The GC has no problems
with class types. Class references do keep objects alive.
That is, the above will not keep the created object any more
alive than the following:
B make_b_thing(int i) { return new B(i); }
That seems to work, but I guess I should try to force the
garbage collector to run to see if I can crash the program.
***BUT***: The really, really weird thing is that even though
you *think* that you have a pointer to a B object, you don't
really. Dereferencing is accepted by the compiler, but it plays
a nasty trick on you:
A B* is not a pointer to the memory of the object. It's a pointer
to a class reference. The class reference itself, B, is a pointer
to the memory of the object, under the hood.
Casting a B to B* makes as little sense as casting it to float*
or char*.
B* p = make_b_thing(42);
writefln("Address of pointer: %s", p);
writefln("Value of i: %s", p.i);
p really is a pointer to the memory of the object. But by typing
it B* you're stating that it's a pointer to a class reference,
which is wrong.
p.i does two dereferences where one would be correct. First, p is
dereferenced. The resulting data is really that of the object.
But it's typed B, so the compiler thinks it's a class reference.
So it takes first bytes of the actual object data, interprets it
as a pointer, dereferences it, and assumes to see the object data
there (wherever that is). Getting the i field of that garbage
location results in some garbage data, of course.
writefln("Value of i: %s", (*p).i);
Same as above. When p is a pointer, then p.i becomes (*p).i
automatically in D.
writefln("Value of i: %s", (cast(B)p).i);
Here the type has only one level of indirection, as it should be.
And everything's fine.
This compiles and runs fine, but produces:
Address of pointer: 7F7EE77CF020
Value of i: 4445040
Value of i: 4445040
Value of i: 42
Maybe it's my C++ background talking, but that seems a bit
counter-intuitive.
I'd say it's your C++ background talking.