__delete

Destroys and then deallocates an object.

In detail, __delete(x) returns with no effect if x is null. Otherwise, it performs the following actions in sequence:

  • Calls the destructor ~this() for the object referred to by x (if x is a class or interface reference) or for the object pointed to by x (if x is a pointer to a struct). Arrays of structs call the destructor, if defined, for each element in the array. If no destructor is defined, this step has no effect.
  • Frees the memory allocated for x. If x is a reference to a class or interface, the memory allocated for the underlying instance is freed. If x is a pointer, the memory allocated for the pointed-to object is freed. If x is a built-in array, the memory allocated for the array is freed. If x does not refer to memory previously allocated with new (or the lower-level equivalents in the GC API), the behavior is undefined.
  • Lastly, x is set to null. Any attempt to read or write the freed memory via other references will result in undefined behavior.

Note: Users should prefer $(REF1 destroy, object) to explicitly finalize objects, and only resort to core.memory.__delete when object.destroy wouldn't be a feasible option.

@system
void
__delete
(
T
)
(
ref T x
)

Parameters

x T

aggregate object that should be destroyed

Examples

Deleting classes

bool dtorCalled;
class B
{
    int test;
    ~this()
    {
        dtorCalled = true;
    }
}
B b = new B();
B a = b;
b.test = 10;

assert(GC.addrOf(cast(void*) b) != null);
__delete(b);
assert(b is null);
assert(dtorCalled);
assert(GC.addrOf(cast(void*) b) == null);
// but be careful, a still points to it
assert(a !is null);
assert(GC.addrOf(cast(void*) a) == null); // but not a valid GC pointer

Deleting interfaces

bool dtorCalled;
interface A
{
    int quack();
}
class B : A
{
    int a;
    int quack()
    {
        a++;
        return a;
    }
    ~this()
    {
        dtorCalled = true;
    }
}
A a = new B();
a.quack();

assert(GC.addrOf(cast(void*) a) != null);
__delete(a);
assert(a is null);
assert(dtorCalled);
assert(GC.addrOf(cast(void*) a) == null);

Deleting structs

bool dtorCalled;
struct A
{
    string test;
    ~this()
    {
        dtorCalled = true;
    }
}
auto a = new A("foo");

assert(GC.addrOf(cast(void*) a) != null);
__delete(a);
assert(a is null);
assert(dtorCalled);
assert(GC.addrOf(cast(void*) a) == null);

// https://issues.dlang.org/show_bug.cgi?id=22779
A *aptr;
__delete(aptr);

Deleting arrays

int[] a = [1, 2, 3];
auto b = a;

assert(GC.addrOf(b.ptr) != null);
__delete(b);
assert(b is null);
assert(GC.addrOf(b.ptr) == null);
// but be careful, a still points to it
assert(a !is null);
assert(GC.addrOf(a.ptr) == null); // but not a valid GC pointer

Deleting arrays of structs

int dtorCalled;
struct A
{
    int a;
    ~this()
    {
        assert(dtorCalled == a);
        dtorCalled++;
    }
}
auto arr = [A(1), A(2), A(3)];
arr[0].a = 2;
arr[1].a = 1;
arr[2].a = 0;

assert(GC.addrOf(arr.ptr) != null);
__delete(arr);
assert(dtorCalled == 3);
assert(GC.addrOf(arr.ptr) == null);

See Also

$(REF1 destroy, object), core.GC.free

Meta

History

The delete keyword allowed to free GC-allocated memory. As this is inherently not @safe, it has been deprecated. This function has been added to provide an easy transition from delete. It performs the same functionality as the former delete keyword.