Отличается ли постблитовый конструктор только по источнику от конструктора копирования?

Если я правильно понимаю, что постблитовый конструктор в D начинается с побитового копирования (всегда), то это определенное пользователем тело.

Но когда я смотрю на тело конструктора postblit, он очень похож на конструктор копирования C ++, единственное отличие состоит в том, что в C ++ источником является некоторый объект, а в D this (сам).

Я прав?

2

Решение

Эх, близко. Я думаю, что у вас есть довольно хорошая ручка, но по буквам:

a = b; (если a и b имеют одинаковый тип, структура) переводится в:

memcpy(&a, &b, b.sizeof); // bitwise copy
a.__postblit(); // call the postblit on the destination only (iff this(this) is defined on the type!)

Таким образом, вам не нужно явно назначать какие-либо переменные в постблите (они все копируются автоматически), а также нельзя использовать его для реализации семантики перемещения (у вас нет доступа к источнику).

Я чаще всего использую postblit, когда структура является указателем на другой объект, поэтому я могу увеличить refcount:

struct S {
SomeObject* wrapped;
this(this) { if(wrapped) wrapped.addReference(); }
~this() { if(wrapped) wrapped.releaseReference(); }
}

Это работает только со ссылками, так как в противном случае вы будете увеличивать копию переменной!

Вы Можно (но не следует) также использовать его для выполнения глубоких копий:

struct S {
string content;
this(this) { content = content.idup; }
}

Но на самом деле это плохая идея, поскольку назначение структуры должно быть универсально дешевым в D, а глубокие копии не дешевы. Как правило, в этом нет необходимости, так как сборщик мусора обрабатывает такие случаи, как double free, где вы могли бы захотеть этого в C ++.

Другой случай, когда я часто использую его в D, это его отключение:

struct S {
@disable this(this);
}
S a, b;
a = b; // compile error, b is not copyable

Это отличается от того, чтобы просто не реализовывать postblit, что оставляет вас с автоматической реализацией memcpy. Это делает присваивание явной ошибкой компиляции, которую вы можете использовать, чтобы направить пользователя к другому методу, например, для семантики перемещения:

struct S {
int* cool;
@disable this(this);
S release() { auto n = cool; cool = null; return S(cool); }
}

Поскольку a = b запрещено, теперь мы можем заставить пользователя использовать метод .release, когда он хочет переназначить его, что делает наше перемещение.

3

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector