3

Читщит По Умным Указателям

Читщит По Умным Указателям Обучение, Rust, Программирование, C++, Длиннопост

Наглядная иллюстрация того, что может случиться с C++ программистами.

В Rust необычная схема управления памятью. Он не использует сборщик мусора, как в Java и Go, что делает его быстрым. Скорость Rust сопоставима со скоростью C.

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

В статье специально использованы простейшие примеры, чтобы понять их было легче.

Типы

Box

Нужен для хранения объектов в куче, а не на стеке.

Обычно используется для рекурсивных типов, где размер объекта неизвестен во время компиляции.

Пример кода, который не будет работать.

struct Expression {

operator: Operator,

left: Expression, // Ошибка: recursive type has infinite size

right: Expression, // Ошибка: recursive type has infinite size

}

Чинится обертыванием left и right в Box.

struct Expression {

operator: Operator,

left: Box<Expression>,

right: Box<Expression>,

}

Rc

Позволяет нескольким переменным владеть одним объектом размещенным в куче.

Не работающий код.

let a = "Hello, World!".to_string();

let b = a;

let c = a; // Ошибка: use of moved value

Чтобы он заработал, добавим Rc.

let a = Rc::new("Hello, World!".to_string());

let b = Rc::clone(&a);

let c = Rc::clone(&a);

Код также будет работать если мы скопируем объект.

let a = "Hello, World!".to_string();

let b = a.clone();

let c = a;

Но прямое копирование может серьезно повредить производительности. Преимущество Rc в том, что при присваивании не создаётся новый объект, а даётся ссылка на уже существующий.

Arc

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

let a = Arc::new(1);

let b = Arc::clone(&a);

let c = Arc::clone(&a);

Дороже с точки зрения производительности из-за способа подсчёта ссылок.

RefCell

Позволяет изменять данные внутри себя даже если объявлен как неизменяемый.

let a = RefCell::new(1);

*a.borrow_mut() += 1;

dbg!(a); // 2

Комбо

RefCell часто комбинируют с Rc в виде Rc<RefCell<T>>. Это позволяет каждому владельцу ссылки изменять общий объект.

let a = Rc::new(RefCell::new(1));

let b = Rc::clone(&a);

let c = Rc::clone(&a);

*b.borrow_mut() += 1;

dbg!(&a); // 2

dbg!(&c); // Тоже 2

*c.borrow_mut() += 1;

dbg!(&a); // 3

dbg!(&b); // Тоже 3

Заключение

Главное преимущество умных указателей – избегание ошибок типа segfault и выстрелов в ногу, характерных для C и C++, сохраняя при этом удобство использования.

Если статья была полезной, вас могут заинтересовать и другие статьи в моём телеграм-канале.

Лига программистов

2K постов11.8K подписчиков

Правила сообщества

- Будьте взаимовежливы, аргументируйте критику

- Приветствуются любые посты по тематике программирования

- Если ваш пост содержит ссылки на внешние ресурсы - он должен быть самодостаточным. Вариации на тему "далее читайте в моей телеге" будут удаляться из сообщества

0
Автор поста оценил этот комментарий

Например, указатели без защиты от дурака требующей дополнительных действий от компа и, соответственно, обеспечивающей меньшее быстродействие.

раскрыть ветку (1)
0
Автор поста оценил этот комментарий

В Rust есть сырые указатели, но их нужно использовать в unsafe блоках

показать ответы
1
Автор поста оценил этот комментарий

RefCell

Позволяет изменять данные внутри себя даже если объявлен как неизменяемый.

Очень брутальное объяснение зачем нужен этот тип:) Всё-таки в Rust его используют не чтобы ломать констатность, а чтобы перенести проверку borrowing rules из compile time в run time.


Скучно с этими вводными статьями по Rust, их уже наклепали мильон штук, а материалов по продвинутому Rust практически нет. Смысла же постить/читать ровно 1 вырванную из контекста статью по основам Rust я вообще не вижу. Зачем мне идти в тг канал? Там полноценный вводный курс по Rust или огрызок типа этого? Почему не взять проверенный материал, rustbook/rustlings?

раскрыть ветку (1)
Автор поста оценил этот комментарий

Ждите вторую часть)

0
Автор поста оценил этот комментарий

Главное преимущество умных указателей – избегание ошибок типа segfault и выстрелов в ногу, характерных для C и C++

В плюсах тоже есть умные указатели.


PS может мне кто-нибудь объяснить, почему реклама Rust строится на том, что он, типо, как С++, но с урезанным функционалом?

раскрыть ветку (1)
Автор поста оценил этот комментарий

Ну это не то чтобы реклама. C++ известен своими "приколами", поэтому и приводится в пример

2
Автор поста оценил этот комментарий

Слово clone намекает что какая-то копия все-таки создается, иначе нахрена этот процесс так обозначать. Вы уверены, что не создается?

раскрыть ветку (1)
Автор поста оценил этот комментарий

Создается ссылка на объект. Это никак не ощущается на перформансе