Вопросы о постблите и семантике перемещения - PullRequest
14 голосов
/ 30 июля 2011

Я уже задавал аналогичный вопрос некоторое время назад, но мне все еще неясно некоторые детали.

  1. При каких обстоятельствах конструктор postblit называется?

  2. Какова семантика перемещения объекта?Будет ли он постблитован и / или уничтожен?

  3. Что произойдет, если я верну локальную переменную по значению?Будет ли оно неявно перемещено?

  4. Как преобразовать выражение в значение?Например, как будет выглядеть общий своп?

Ответы [ 2 ]

16 голосов
/ 31 июля 2011
  1. Постбликовый конструктор вызывается всякий раз, когда структура копируется - например, при передаче структуры в функцию.

  2. Ход является побитовой копией. Постблитовый конструктор никогда не вызывается. Деструктор никогда не называется. Биты просто копируются. Оригинал был «перемещен», поэтому ничего не нужно создавать или уничтожать.

  3. Будет перемещено. Это основной пример хода.

  4. Существует ряд различных ситуаций, о которых функция swap должна беспокоиться, если вы хотите сделать ее максимально эффективной. Я бы посоветовал просто использовать функцию swap в std.algorithm . Классический обмен приведет к копированию и вызовет конструктор postblit и деструктор. Перемещения обычно выполняются компилятором, а не программистом. Однако, , глядя на официальную реализацию из swap, похоже, что он играет некоторые хитрости, чтобы получить семантику перемещения из сделки, где это возможно. Независимо от того, ходы обычно выполняются компилятором. Это оптимизация, которую он будет делать, когда знает, что может ( RVO - классический случай, когда это возможно).

Согласно TDPL (стр. 251), есть только 2 случая, когда D гарантирует , что перемещение произойдет:

  • Все анонимные значения перемещаются, а не копируются. Звонок на this(this) никогда не вставляется, когда источником является анонимное значение (т. е. временно, как указано в функции hun выше).
  • Все именованные временные столбцы, которые размещаются в стеке внутри функции и затем вернул elide вызов на this(this).
  • Нет гарантии, что соблюдаются другие потенциальные решения.

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

4 голосов
/ 30 июля 2011

Насколько я понимаю:

1) Когда структура копируется, а не перемещается или создается.

2) Смысл семантики перемещения заключается в том, что ни одно из двух не должно происходить. Новое расположение структуры инициализируется побитовой копией структуры, а старое расположение выходит из области видимости и становится недоступным. Таким образом, структура «переместилась» из А в Б.

3) Это типичная ситуация с ходом:

S init(bool someFlag)
{
    S s;
    s.foo = someFlag? bar : baz;
    return s; // `s` can now be safely moved from here...
}

// call-site:
S s = init(flag);
//^ ... to here.
...