Rust
2.2K subscribers
148 photos
101 videos
2 files
201 links
Полезный контент по программированию на Rust
Download Telegram
🤠 Трюк Индианы Джонса: std::mem::take

Типичная ситуация: у вас есть &mut self, и вы хотите забрать поле (например, String или Vec), что-то с ним сделать, и, возможно, вернуть обратно или сохранить измененную версию.

Компилятор бьет по рукам: нельзя просто так переместить (move) значение из-за мутабельной ссылки. Новички часто делают .clone(), чтобы успокоить borrow checker. Но это лишняя аллокация!

Решение: std::mem::take.

Оно забирает значение из ссылки, оставляя на его месте Default::default().


struct Buffer {
data: Vec<u8>,
}

impl Buffer {
fn process(&mut self) {
// Мы "выкрадываем" вектор.
// В self.data теперь пустой Vec (без аллокаций).
let raw_data = std::mem::take(&mut self.data);

// Тяжелая обработка в другом потоке/функции,
// требующая владения (ownership)
let processed = heavy_transform(raw_data);

// Возвращаем результат
self.data = processed;
}
}



Это работает для всего, что реализует Default (Option, String, Vec). Для типов без Default есть std::mem::replace.

Это zero-cost, семантически верно и намного быстрее клонирования.

#rust #std #optimization #tips

👉 @rust_lib
🔥25👍86🥰1😁1🤗1
⚡️ Забудь про RefCell для примитивов

Вам нужно изменить поле внутри неизменяемой структуры (&self).
Рука тянется к RefCell? Стоп.

RefCell имеет оверхед:

1. Хранит счетчик заимствований (borrow count).
2. В рантайме проверяет правила (может паниковать!).

Если ваш тип реализует Copy (числа, bool, маленькие структуры) - используйте Cell.

В чем магия Cell?
У него нет никакого рантайм-оверхеда. Вообще. Он не проверяет заимствования.
Он работает так: "Я даю тебе копию значения" (get) или "Я заменяю значение целиком" (set). Вы не можете получить ссылку (&) на содержимое Cell, поэтому правила Rust не нарушаются.


use std::cell::Cell;

struct Metric {
count: Cell<u64>, // Zero overhead
}

impl Metric {
fn inc(&self) {
// Мы меняем значение по неизменяемой ссылке &self
let current = self.count.get();
self.count.set(current + 1);
}
}



Это атомарно? Нет. Это работает только в одном потоке. Но для однопоточного кода (или внутри thread_local) это самая быстрая мутабельность, которая только возможна.

#rust #std #optimization #interior_mutability

👉 @rust_lib
👍1361🥰1🤗1