[Перевод] Графическое описание владения и заимствования в Rust

Ниже представлено графическое описание перемещения, копирования и заимствования в языке программирования Rust. В основном, эти понятия специфичны только для Rust, являясь общим камнем преткновения для многих новичков.


b9c43ab326344735aded691730ba6edf.png


Чтобы избежать путаницы, я попытался свести текст к минимуму. Данная заметка не является заменой различных учебных руководств, и лишь сделана для тех, кто считает, что визуально информация воспринимается легче. Если вы только начали изучать Rust и считаете данные графики полезными, то я бы порекомендовал вам отмечать свой код похожими схемами для лучшего закрепления понятий.



Схема


Картинка кликабельна, вы можете её увеличить. Также вы можете получить схемы без перевода в виде PNG, SVG или PDF.


Верхние две схемы изображают два основных вида семантики данных, которые нам доступны: либо перемещение, либо копирование.


  • Схема семантики перемещения (⤳) выглядит очень простой. Здесь нет никакого обмана: семантика перемещения выглядит странной только потому, что большинство языков позволяют использовать переменные столько раз, сколько пожелает программист. В реальном мире обычно всё не так: я не могу просто дать кому-нибудь свою ручку и при этом всё еще использовать её для записи! В Rust, любая переменная, тип которой не реализует типаж Copy, имеет семантику перемещения, поведение которой показано на рисунке.
  • Семантика копирования (⎘) зарезервирована для типов, которые реализуют типаж Copy. В этом случае каждое использование объекта будет приводить к копированию, как показано на схеме — раздвоением.

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


  • Для изменяемого заимствования я использовал символ замка для того, чтобы показать, что исходный объект заблокирован на всё время заимствования, что приводит к невозможности его использования.
  • Для противоположного, неизменяемого заимствования, я использовал символ снежинки, чтобы показать, что исходный объект всего лишь заморожен: вы до сих пор можете брать неизменяемые ссылки, но не можете перемещать или брать изменяемые ссылки на него.

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


Последние две схемы подводят итог, показывая основные отличия и общие черты между двумя видами ссылок, как в виде изображения, так и в виде текста. Спецификатор «внешне» важен, так как у вас может быть внутренняя изменяемость через вещи похожие на Cell.


Примечание переводчика


Хотелось бы выразить отдельную благодарность Андрею Лесникову (@ozkiff), Serhii Plyhun (@snuk182) и Сергею Веселкову (@vessd) за помощь в переводе и последующее ревью.

Комментарии (13)

  • 19 февраля 2017 в 10:10 (комментарий был изменён)

    +2

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

    Я понимаю, что речь идет исключительно о вре́менном даунгрейде &mut до &. Однако, не знакомый с Rust человек может подумать, что это обычное использование неконстантных объектов в константном контексте.

    Имхо, этот момент стоило бы пояснить подробнее.

  • 19 февраля 2017 в 10:16 (комментарий был изменён)

    +6

    Ну и перевод «must not outlive» как «не должна пережить», как мне кажется, не делает достаточного акцента. Может показаться, что программист должен сам это контролировать, тогда как на деле контролирует и запрещает такое компилятор.

    Я бы написал «не может пережить».

  • 19 февраля 2017 в 10:31

    +6

    Заглавная картинка некорректна. Текстом дано определение круга, а нарисована окружность, почему-то подписанная кругом.
    • 19 февраля 2017 в 11:11

      0

      Ну, почему сразу некорректна. Внутри белый круг, граница круга — окружность. Просто несколько двусмысленна.
    • 19 февраля 2017 в 11:11

      +3

      Соглашусь и поправлюсь.
    • 19 февраля 2017 в 13:32

      0

      Еще и в квадрате такого же цвета, что сбивает с толку.
  • 19 февраля 2017 в 16:29

    +1

    Отличная статья, отличный перевод!
    Люблю картинки)
  • 19 февраля 2017 в 16:51

    0

    Я хотел освоить rust, открыл его hello world и он меня очень смутил. Чуть более сложный пример, где требуется ввести имя и программа его печатает. Там задаётся мутабельная строка, потом передаётся процедуре чтения. Но во всём этом меня смущает, что мутабельная строка инициализирована пустой строчкой. Зачем? Если процедура сама заполняет строку, то зачем ей давать какой-то готовый объект, пусть модифицирует ссылку. Каких-то разумных предположений я не смог придумать и отложил раст в долгий ящик.
    • 19 февраля 2017 в 18:55 (комментарий был изменён)

      +1

      Не видел этот пример, так что не скажу почему автор написал именно так, но никто не запрещает создать строку напрямую:


      let mut abc = String::new();

      Это будет действительно немножко эффективнее чем инициализация пустой строкой:


      let mut abc = String::from("");

      Но может автор хотел заодно показать этим примером, как можно создать не только пустые строки, но и с заданным текстом.
      Если очень сильно заботится о производительности, то можно предположить сколько текста будет на входе и выделить память заранее:


      let mut abc = String::with_capacity(10);
    • 19 февраля 2017 в 19:28

      +1

      Но во всём этом меня смущает, что мутабельная строка инициализирована пустой строчкой. Зачем? Если процедура сама заполняет строку, то зачем ей давать какой-то готовый объект, пусть модифицирует ссылку.

      Ссылка не может быть сама по себе, она должна на что-то ссылаться, а про то как создать строку уже рассказал pftbest.

      • 19 февраля 2017 в 22:34

        0

        > Ссылка не может быть сама по себе, она должна на что-то ссылаться

        А что в rust не бывает null?

        • 19 февраля 2017 в 23:25

          +1

          За пределами unsafe не бывает.
          Вместо него есть Option с гораздо более явной семмантикой, чем null.
        • 20 февраля 2017 в 00:34

          +1

          У ссылок нет конечно, это же не указатель.

© Habrahabr.ru