On Saturday, 3 June 2017 at 19:55:30 UTC, ag0aep6g wrote:
On 06/03/2017 09:37 PM, Moritz Maxeiner wrote:
Of course, but AFAIK you'd need to explicitly assign it to an
object, so `ptr` won't null by accident, but only by explicit
programmer intent (same as overwriting the memory the object
lives in via things like `memcpy`); and you can always screw
things intentionally (you could also assign some invalid value
to the pointer via `memcpy`).
I'd say `.init` can easily happen accidentally. Especially when
`@disable this(this);` is involved.
When you can't copy, you may have to move sometimes. But
std.algorithm.move overwrites the old location with `.init`,
assuming that `.init` can safely be destroyed.
----
struct S
{
void* ptr;
@disable this(this);
~this() { assert(ptr !is null); /* fails */ }
}
void f(S s) {}
void main()
{
auto a = S(new int);
import std.algorithm: move;
f(move(a)); /* overwrites `a` with `S.init` */
}
----
Yep, that's exactly why I added the null check in the example. If
the struct has a postblit or a destructor, `move` will be
destructive, and will overwrite the source with .init. Sometimes
it doesn't matter (i.e. free() is allowed to take a null
pointer), but in general, for things like smart pointers where
you'd do arbitrary access in destructor, it's a good habit to
check for .init values first, in case the object has been moved.