Is it possible to avoid call to destructor for structs?
Biotronic
simen.kjaras at gmail.com
Sun Sep 24 19:24:53 UTC 2017
On Sunday, 24 September 2017 at 18:46:15 UTC, Haridas wrote:
> Also consider the following code. Please let me know if I am
> doing the right thing for dynamic arrays. My hack seems to have
> the desired effect on shutting down the destructor. Is this
> hack legal use of D? Can you please guide me if/how it can be
> achieved for std.container.Array?
>
> // >>>>
> import std.stdio;
>
> struct Bar {
> ~this() {
> writeln("~Bar");
> }
> }
>
> void main() {
> { // dynamic array
> Bar[] bars;
> bars.length = 4;
> void* tmp = bars.ptr;
> delete(tmp);
> bars.length = 0;
> }
> { // std.container.Array
> import std.container: Array;
> Array!Bar bars;
> bars.length = 6;
> // does not seem to work
> void* tmp = &(bars[0]);
> delete(tmp);
> bars.length = 0;
> }
> }
Since you're deleting the memory the dynamic array is pointing
to, what you're doing is potentially unsafe - if anyone touches
that memory after it's been deleted, nasal demons may follow.
What you want is something like this:
import std.stdio;
struct Bar
{
this(int n) {}
~this()
{
writeln("~Bar");
}
}
struct SuppressGC(T)
{
// Disguise T as a humble array.
private ubyte[T.sizeof] _payload;
// Create from instance of T.
this(T arg) {
_payload = *cast(ubyte[T.sizeof]*)&arg;
}
// Or forward constructor arguments to T's constructor.
static if (__traits(hasMember, T, "__ctor"))
{
this(Args...)(Args args)
if (__traits(compiles, (Args e){__traits(getMember,
T.init, "__ctor")(e);}))
{
__traits(getMember, get, "__ctor")(args);
}
}
// Pretend to be a T.
@property
ref T get()
{
return *cast(T*)_payload.ptr;
}
alias get this;
}
void useBar(ref Bar b) {}
unittest
{
// Construct from instance.
//This creates a temporary on the stack, and its destructor
will be called.
SuppressGC!Bar a = Bar(3);
// Or by forwarding constructor arguments.
// This constructs in-place inside SuppressGC, and no
destructor will be called.
auto b = SuppressGC!Bar(3);
SuppressGC!Bar[] arr;
arr.length = 3;
// Another stack temporary. Destructor will be called.
arr[0] = Bar(5);
// No temp
arr[1] = SuppressGC!Bar(5);
// It even pretends to be the wrapped struct:
useBar(b);
}
In general, of course, this is a bad idea - there's probably a
reason that destructor does the thing it's doing. If you're sure
skipping it is what you want, go ahead.
--
Biotronic
More information about the Digitalmars-d-learn
mailing list