TGViewer
DEV: Рубиновые тона DEV: Рубиновые тона @dev_in_ruby_colors · 3.28K subscribers
Post #1016 1.23K
let a = String::from("test");
let b = a.deref();


Тип b будет &str (если бы там был вектор, тип бы стал &[i32]). Чувствуете разницу? Этот метод сделает указатель непосредственно на данные, но он не попытается эти данные куда-то перенести. Если же перед deref поставить звёздочку, то мы опять получим ошибку: *(a.deref()), потому что опять будет сделана попытка вытащить сами данные из heap и куда-то их перетащить. Фактически, здесь *(a.deref()) равносильно *a.

При этом для простых типов deref не имеет смысла. На типах вроде i32 его нет вовсе, на указателях это метод просто вернёт сам указатель:

let a: i32 = 5;
let b = &a;
let c = b.deref();


Тип c будет &i32, как у b.

Интересно, что в ряде случаев Rust умеет делать dereference автоматически для нашего же удобства. К примеру, есть функция:

fn call(s: &str) {
println!("{}", s);
}


Она может принять как &str, так и String:

let a = "test";
let b = String::from(a);

call(a);
call(&b);


Работает это потому, что у String есть trait Deref (про него будет в видео), который умеет делать dereferencing в обычный &str.

То есть функция делает что-то такое:

let borrowed = &b;
let my_str = c.deref();


Тип my_str будет &str, то есть ровно то, что написано в функции. Хотя мы могли бы сделать слайс &str сами, это уж очень неудобно, ведь нужно получить сами данные из умного указателя, сделать заимствование, и потом создать слайс:

let borrowed = &b;
let my_str = &(*borrowed)[..];


А так deref() вызовется для нас, причём столько раз, сколько требуется, поэтому если функция принимает массив вида &[i32], то туда можно запихнуть и вектор с числами того же типа.

Теперь мы понимаем, какие есть указатели и как из них получать данные. Интересно, что мы можем создавать и свои умные указатели в Rust, и самым простым является Box - он положит наши данные в heap и сделает привязку к ним по аналогии с тем, что делает vector или string:

let a: Box<i32> = Box::new(42);


То есть наши число теперь торчит не в стеке, а в heap, и a содержит в себе умный указатель. Это значит, что мы можем тоже делать referencing и dereferencing:

let a: Box<i32> = Box::new(42);
let b: &Box<i32> = &a;
let c: &i32 = a.deref();
let d: i32 = *a;


Из аннотации типов можно легко видеть, где что получается. Кстати, *a тут тоже работает в отличие от истории с векторами и строками, потому что размер целого числа точно известен, его можно скопировать и поместить в стек. То есть в d будет число, независимое от того, на которое указывает a (там вообще выходит, что он сначала делает deref, потом звёздочку).
Однако вот так всё равно сделать нельзя: let e = *b;, как и в предыдущих примерах. *b укажет на сам Box<i32>, копировать его автоматом Rust не будет, так что там придётся написать clone()

Но тут вопрос: зачем нам вообще этот box нужен, если лучше хранить простые типы в стеке, который банально быстрее работает? Это так и есть, во многих случаях хранить обычное число "в коробке" смысла нет. Но если у нас есть данные, размер которых заранее неизвестен, то это может быть очень актуально.

К примеру, есть вот такая структура, описывающая кошку:

struct Cat {
name: String,
age: u8,
}

let cat = Cat {
name: String::from("Mr. Buttons"),
age: 3,
};


Где будет хранится наш Mr. Buttons? Сама структура будет в стеке, но строка как таковая будет в heap (в стеке же будет указатель на неё).

Однако предположим, что у кошки может быть предок, и это тоже кошка:

struct Cat {
name: String,
age: u8,
parent: Option<Cat>,
}


Можно ли такую структуру запихнуть в стек? Нет, потому что она рекурсивная, и её размер во время компиляции определить невозможно. Дело в том, что у Mr. Buttons может быть потомок, у того свой потомок, и так до бесконечности. Поэтому родителя нужно хранить в heap, и это тот случай, когда нам нужен Box:

struct Cat {
name: String,
age: u8,
parent: Option<Box<Cat>>,
}


Создадим двух кошек:
  • 👍 5
More from @dev_in_ruby_colors
  1. Sep 28, 2026Github буйствует
  2. Sep 26, 2026В этом уроке по абстрактной алгебре говорим про области целостности, делители нуля, характ…
  3. Sep 22, 2026А тем временем сказ о ведьмаке, потерявшем память, уже доступен в виде аудиокниги. Целых 1…
  4. Sep 20, 2026В этом уроке по абстрактной алгебре продолжаем говорить о кольцах: в частности о subrings…
  5. Sep 17, 2026Сделал обзор актуальных библиотек JS для сбора данных, 10 штук бодрых решений на все случа…
  6. Sep 13, 2026В общем, мне тут особо было нечего делать и я подумал создать небольшой скрипт для решения…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →