Вопрос

Проблема «типов ценностей» с внешними ресурсами (например, std::vector<T> или std::string) заключается в том, что копирование их имеет тенденцию быть достаточно дорогими, и копии создаются неявно в различных контекстах, поэтому это имеет тенденцию быть проблемой производительности. Ответ C ++ 0x на эту проблему Переместить семантику, который концептуально на основании идеи во врезании ресурсов и технически включенным Rvalue ссылки.

У d есть что-нибудь похожее на перемещение семантики или ссылок на рвале?

Это было полезно?

Решение

Я считаю, что в D (например, есть несколько мест в D (например, возвратные структуры), которые d удается сделать их перемещениями, тогда как C ++ сделает их копией. IIRC, компилятор будет делать ход, а не копию в любом случае, где она может определить, что копия не требуется, поэтому скопирование структуры произойдет меньше в D, чем в C ++. И, конечно же, поскольку классы - это ссылки, у них нет проблем вообще.

Но независимо от копирования конструкция уже работает по-разному в D, чем в C ++. Вообще, вместо того, чтобы объявлять Copy Constructor, вы объявляете постбит-конструктор: this(this). Отказ Это делает полный мемкпи до this(this) Вызывается, и вы только делаете все возможные изменения, чтобы гарантировать, что новый структурь отделен от оригинала (например, делать глубокую копию переменных элементов, где это необходимо), в отличие от создания совершенно нового конструктора, который должен скопировать все. Итак, общий подход уже немного отличается от C ++. Также в целом согласовано эти структуры не должны иметь дорогих постбитных конструкторов - копирование структуров должно быть дешевым - так что это меньше проблем, чем в C ++. Объекты, которые были бы дорогими для копирования, обычно являются либо классами, либо структурами со ссылкой или семантикой COW.

Контейнеры, как правило, являются ссылочными типами (в фобосе, они строки, а не классы, поскольку они не нуждаются в полиморфизме, но копирование их не копирует их содержимое, поэтому они все еще ссылочные типы), поэтому копирование их не дорого Как будто это будет в C ++.

Там могут быть вполне могут быть случаи в D, где он мог использовать что-то похожее на конструктор движения, но в целом D был разработан таким образом, чтобы уменьшить проблемы, которые C ++ с копированием объектов вокруг, так что это никуда рядом с проблемой что это в C ++.

Другие советы

D имел отдельное значение и семантику объекта:

  • Если вы объявите свой тип как struct, он будет иметь значение семантики по умолчанию
  • Если вы объявите свой тип как class, У него будет объект семантической.

Теперь, если предположить, что вы не управляете памятью самостоятельно, так как это случай по умолчанию в D - с помощью сборщика мусора - вы должны понимать, что объект типов объявлен как class автоматически указатели (или «ссылка», если вы предпочитаете) к реальному объекту, а не сам реальный объект.

Итак, при прохождении векторов в D, то, что вы проходите, является эталонным / указателем. Автоматически. Нет копии (кроме копии ссылки).

Вот почему D, C #, Java и другой язык не «нуждаются в движущихся семантических условиях (поскольку большинство типов - это объект семантической и манипулируется посредством ссылки, а не копией).

Может быть, они могли бы реализовать это, я не уверен. Но бы они действительно получили повышение производительности, как в C ++? По природе, это не кажется вероятным.

Я каким-то образом у меня есть ощущение, что на самом деле ссылки на рвале и вся концепция «семантики движения» является следствием, что это нормально в C ++ для создания локальных «временных» объектов стека. В D и большинству языков Gc, наиболее распространенным, имеющим объекты на куче, а затем нет накладных расходов, имея временный объект, скопированный (или перемещаемый) несколько раз, когда возвращая его через стек вызова - Таким образом, нет необходимости в механизме, чтобы избежать этого накладных расходов.

В D (и большинство языках GC) class объект никогда не копируется неявно, и вы проходите только в большую часть времени, так что это мая означает, что вам не нужны какие-либо ссылки на Rvalue для них.

ОТОЧ, struct Объекты не должны быть «ручками к ресурсам», но простые типы значений ведут себя похоже на встроенные типы - так что еще раз, нет причин для любой семантики движения здесь, IMHO.

Это дало бы заключение - D не имеет RValue Refs, потому что они не нуждаются в.

Тем не менее, я не использовал ссылки на RVALUE на практике, у меня только было прочитать их, поэтому я мог бы пропустить некоторые фактические случаи использования этой функции. Пожалуйста, обратитесь к этому посту как куча мыслей по этому вопросу, который, надеюсь, будет полезен для вас, а не как надежное суждение.

Я думаю, что все ответы полностью не смогли ответить на оригинальный вопрос.

Во-первых, как указано выше, вопрос имеет отношение только к структурам. Классы не имеют значимого движения. Также указано выше, для структуру определенное количество хода произойдет автоматически с помощью компилятора при определенных условиях.

Если вы хотите получить контроль над операциями на ходу, вот что вы должны сделать. Вы можете отключить копирование, аннотируя это (это) с @disable. Далее вы можете переопределить C ++ constructor(constructor &&that) определяя this(Struct that). Отказ Аналогично, вы можете переопределить назначение с opAssign(Struct that). Отказ В обоих случаях вам необходимо убедиться, что вы уничтожаете значения that.

Для назначения, поскольку вам также нужно уничтожить старое значение this, Самый простой способ - это поменять их. Внедрение C ++ unique_ptr Поэтому будет выглядеть что-то вроде этого:

struct UniquePtr(T) {
    private T* ptr = null;

    @disable this(this); // This disables both copy construction and opAssign

    // The obvious constructor, destructor and accessor
    this(T* ptr) {
        if(ptr !is null)
            this.ptr = ptr;
    }

    ~this() {
        freeMemory(ptr);
    }

    inout(T)* get() inout {
        return ptr;
    }

    // Move operations
    this(UniquePtr!T that) {
        this.ptr = that.ptr;
        that.ptr = null;
    }

    ref UniquePtr!T opAssign(UniquePtr!T that) { // Notice no "ref" on "that"
        swap(this.ptr, that.ptr); // We change it anyways, because it's a temporary
        return this;
    }
}

Редактировать: Обратите внимание, что я не определял opAssign(ref UniquePtr!T that). Отказ Это оператор назначения копирования, и если вы попытаетесь его определить, компилятор ошибся, потому что вы объявили, в @disable Линия, что у вас нет такой вещи.

Я думаю, что если вам нужен источник, чтобы потерять ресурс, вы можете быть в беде. Однако в том, что вы часто можете избежать необходимости беспокоиться о нескольких владельцах, поэтому он не может быть проблемой для большинства случаев.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top