Присвояване, копиране, референции
11 октомври 2022
Административни неща
- Инсталирайте си Rust: https://rustup.rs/
Административни неща
- Инсталирайте си Rust: https://rustup.rs/
- Елате в Discord канала: https://discord.gg/FCTNfbZ
Административни неща
- Инсталирайте си Rust: https://rustup.rs/
- Елате в Discord канала: https://discord.gg/FCTNfbZ
- Първото предизвикателство приключва днес
Административни неща
- Инсталирайте си Rust: https://rustup.rs/
- Елате в Discord канала: https://discord.gg/FCTNfbZ
- Първото предизвикателство приключва днес
- Нека започнем с преговор на материала от миналата лекция
Въпрос 1
Намерете грешката
let x = 3;
let y = 5_i32;
x = x + y;
println!("{}", x);
Въпрос 1
Намерете грешката
let x = 3;
let y = 5_i32;
x = x + y;
println!("{}", x);
error[E0384]: cannot assign twice to immutable variable `x` --> src/bin/main_793bd1e82f6a5e8e900d20244b579b139e851656.rs:6:1 | 3 | let x = 3; | - | | | first assignment to `x` | help: consider making this binding mutable: `mut x` ... 6 | x = x + y; | ^^^^^^^^^ cannot assign twice to immutable variable For more information about this error, try `rustc --explain E0384`. error: could not compile `rust` due to previous error
fn main() { let x = 3; let y = 5_i32; x = x + y; println!("{}", x); }
Въпрос 1
Как може да я оправим?
let x = 3;
let y = 5_i32;
let x = x + y;
println!("{}", x);
8
fn main() { let x = 3; let y = 5_i32; let x = x + y; println!("{}", x); }
Въпрос 2
Намерете грешката
let x = 3.14_f32 as u32;
let y = 5_i32;
let z = x + y;
println!("{}", z);
Въпрос 2
Намерете грешката
let x = 3.14_f32 as u32;
let y = 5_i32;
let z = x + y;
println!("{}", z);
error[E0308]: mismatched types --> src/bin/main_2e0ed2c7322a9afaac10ab153c9b25e128a54dd9.rs:6:13 | 6 | let z = x + y; | ^ expected `u32`, found `i32` error[E0277]: cannot add `i32` to `u32` --> src/bin/main_2e0ed2c7322a9afaac10ab153c9b25e128a54dd9.rs:6:11 | 6 | let z = x + y; | ^ no implementation for `u32 + i32` | = help: the trait `Add<i32>` is not implemented for `u32` = help: the following other types implement trait `Add<Rhs>`: <&'a f32 as Add<f32>> <&'a f64 as Add<f64>> <&'a i128 as Add<i128>> <&'a i16 as Add<i16>> <&'a i32 as Add<i32>> <&'a i64 as Add<i64>> <&'a i8 as Add<i8>> <&'a isize as Add<isize>> and 48 others Some errors have detailed explanations: E0277, E0308. For more information about an error, try `rustc --explain E0277`. error: could not compile `rust` due to 2 previous errors
fn main() { let x = 3.14_f32 as u32; let y = 5_i32; let z = x + y; println!("{}", z); }
Въпрос 2
Как може да я оправим?
let x = 3.14_f32 as u32;
let y = 5_i32;
let z = (x as u8) + (y as u8);
println!("{}", z);
8
fn main() { let x = 3.14_f32 as u32; let y = 5_i32; let z = (x as u8) + (y as u8); println!("{}", z); }
Преговор
- Инсталация и подкарване (
rustup
,cargo
, Rust Playground)
Преговор
- Инсталация и подкарване (
rustup
,cargo
, Rust Playground) - Документация (The Rust Book,
rustup doc
)
Преговор
- Инсталация и подкарване (
rustup
,cargo
, Rust Playground) - Документация (The Rust Book,
rustup doc
) - Числа (конвертиране)
Преговор
- Инсталация и подкарване (
rustup
,cargo
, Rust Playground) - Документация (The Rust Book,
rustup doc
) - Числа (конвертиране)
- Променливи (отгатване на типове, скриване на променливи, мутация)
Преговор
- Инсталация и подкарване (
rustup
,cargo
, Rust Playground) - Документация (The Rust Book,
rustup doc
) - Числа (конвертиране)
- Променливи (отгатване на типове, скриване на променливи, мутация)
- Control flow (
if
,while
,loop
)
Преговор
- Инсталация и подкарване (
rustup
,cargo
, Rust Playground) - Документация (The Rust Book,
rustup doc
) - Числа (конвертиране)
- Променливи (отгатване на типове, скриване на променливи, мутация)
- Control flow (
if
,while
,loop
) - Твърдения и изрази (точка-и-запетаи!)
Преговор
- Инсталация и подкарване (
rustup
,cargo
, Rust Playground) - Документация (The Rust Book,
rustup doc
) - Числа (конвертиране)
- Променливи (отгатване на типове, скриване на променливи, мутация)
- Control flow (
if
,while
,loop
) - Твърдения и изрази (точка-и-запетаи!)
- Функции (
fn
, връщане на стойности)
Преговор
- Инсталация и подкарване (
rustup
,cargo
, Rust Playground) - Документация (The Rust Book,
rustup doc
) - Числа (конвертиране)
- Променливи (отгатване на типове, скриване на променливи, мутация)
- Control flow (
if
,while
,loop
) - Твърдения и изрази (точка-и-запетаи!)
- Функции (
fn
, връщане на стойности) - Печатане на стандартния изход (
println!("x = {}", x)
)
Присвояване
Числа
let a = 7;
let b = a;
fn main() { let a = 7; let b = a; }
Присвояване
Числа
let a = 7;
let b = a;
println!("a = {}, b = {}", a, b);
a = 7, b = 7
fn main() { let a = 7; let b = a; println!("a = {}, b = {}", a, b); }
Присвояване
Статични низове
let a = "Hello";
let b = a;
fn main() { let a = "Hello"; let b = a; }
Присвояване
Статични низове
let a = "Hello";
let b = a;
println!("{}!", a);
println!("{} again!", b);
Hello! Hello again!
fn main() { let a = "Hello"; let b = a; println!("{}!", a); println!("{} again!", b); }
Присвояване
Динамични низове
let s1 = String::from("Cookies!");
let s2 = s1;
fn main() { let s1 = String::from("Cookies!"); let s2 = s1; }
Присвояване
Динамични низове
let s1 = String::from("Cookies!");
let s2 = s1;
println!("{}", s1);
println!("Mmm, {}", s2);
Присвояване
Динамични низове
let s1 = String::from("Cookies!");
let s2 = s1;
println!("{}", s1);
println!("Mmm, {}", s2);
error[E0382]: borrow of moved value: `s1` --> src/bin/main_9bd3356d7798f6992589bc25a22e3d30f92002bb.rs:5:16 | 2 | let s1 = String::from("Cookies!"); | -- move occurs because `s1` has type `String`, which does not implement the `Copy` trait 3 | let s2 = s1; | -- value moved here 4 | 5 | println!("{}", s1); | ^^ value borrowed here after move | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) For more information about this error, try `rustc --explain E0382`. error: could not compile `rust` due to previous error
fn main() { let s1 = String::from("Cookies!"); let s2 = s1; println!("{}", s1); println!("Mmm, {}", s2); }
Присвояване
Разполагане в паметта
Разполагане в паметта
String - динамичен низ
Разполагане в паметта
s2 = s1
Вариант: побитово копиране на стека → двойна деалокация
Разполагане в паметта
s2 = s1
Вариант: копие на стека и на динамичната памет - може да доведе до забавяне
Семантика на местене (Move semantics)
Вместо копиране, което е скъпо в някои случаи, Rust използва местене
let s1 = String::from("Cookies!");
let s2 = s1;
println!("{}", s1);
println!("Mmm, {}", s2);
error[E0382]: borrow of moved value: `s1` --> src/bin/main_9bd3356d7798f6992589bc25a22e3d30f92002bb.rs:5:16 | 2 | let s1 = String::from("Cookies!"); | -- move occurs because `s1` has type `String`, which does not implement the `Copy` trait 3 | let s2 = s1; | -- value moved here 4 | 5 | println!("{}", s1); | ^^ value borrowed here after move | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) For more information about this error, try `rustc --explain E0382`. error: could not compile `rust` due to previous error
fn main() { let s1 = String::from("Cookies!"); let s2 = s1; println!("{}", s1); println!("Mmm, {}", s2); }
А защо това е проблем при String
, а не при литералите?
А защо това е проблем при String
, а не при литералите?
Литералите използват статична памет, която не може да бъде променяна
Клониране
trait Clone
Клониране
trait Clone
- типовете които го имплементират имат метод
clone
Клониране
trait Clone
- типовете които го имплементират имат метод
clone
clone
създава копие на обекта
Клониране
Ако сме сигурни, че искаме да клонираме низа, може да използваме .clone()
let s1 = String::from("Cookies!");
let s2 = s1.clone();
println!("{}", s1);
println!("Mmm, {}", s2);
Cookies! Mmm, Cookies!
fn main() { let s1 = String::from("Cookies!"); let s2 = s1.clone(); println!("{}", s1); println!("Mmm, {}", s2); }
Клониране и копиране
trait Copy
Клониране и копиране
trait Copy
- типа, който го имплементира позволява побитово копиране на паметта
Клониране и копиране
trait Copy
- типа, който го имплементира позволява побитово копиране на паметта
- за типове, които са
Copy
не се използва семантика на местенето
Клониране и копиране
trait Copy
- типа, който го имплементира позволява побитово копиране на паметта
- за типове, които са
Copy
не се използва семантика на местенето - при присвояване те се копират - семантика на копирането
Копиране
Числените типове имплементират Copy
let n1 = 0xbeef;
let n2 = n1; // копира s2
let n3 = n1.clone(); // еквивалентно на `n3 = n1`
println!("{}", n2);
println!("Mmm, {:#x}", n3);
48879 Mmm, 0xbeef
fn main() { let n1 = 0xbeef; let n2 = n1; // копира s2 let n3 = n1.clone(); // еквивалентно на `n3 = n1` println!("{}", n2); println!("Mmm, {:#x}", n3); }
Собственост
Ownership
Собственост и заемане
Собственост
{
let a = 123;
// ...
}
Собственост и заемане
Собственост
{
let a = 123;
// ...
}
- Променливата
a
е валидна от декларацията до края на scope-a
Собственост
Правила
Собственост
Правила
- Всяка стойност в Rust си има променлива, която е неин собственик
Собственост
Правила
- Всяка стойност в Rust си има променлива, която е неин собственик
- Стойността може да има само един собственик по всяко време
Собственост
Правила
- Всяка стойност в Rust си има променлива, която е неин собственик
- Стойността може да има само един собственик по всяко време
- Когато собственикът излезе от scope, се извиква деструктора на стойността
Собственост
Функции с подаване на String
При подаването на аргументи към функция важат същите семантики
fn main() {
let s = String::from("hello"); // Дефинираме s
takes_ownership(s); // Стойността на s се мести във функцията и
// затова не е валидна след този ред.
} // Тук s излиза от scope, но s е преместен и съответно не се деалокация.
fn takes_ownership(some_string: String) {
println!("{}", some_string);
} // some_string излиза от scope и се освобождава паметта.
hello
fn main() { let s = String::from("hello"); // Дефинираме s takes_ownership(s); // Стойността на s се мести във функцията и // затова не е валидна след този ред. } // Тук s излиза от scope, но s е преместен и съответно не се деалокация. fn takes_ownership(some_string: String) { println!("{}", some_string); } // some_string излиза от scope и се освобождава паметта.
Собственост
Функции с подаване на число
При подаването на аргументи към функция важат същите семантики
fn main() {
let x = 5; // Дефинираме x
makes_copy(x); // Тук стойността на x би се преместила във функцията,
// но i32 е Copy, затова може да използваме x в последствие.
println!("This was a triumph");
println!("x is still alive");
println!("with the value of {}", x);
} // Тук x излиза от scope.
fn makes_copy(some_integer: i32) {
println!("{}", some_integer);
} // some_integer излиза от scope, но не се случва нищо особено.
5 This was a triumph x is still alive with the value of 5
fn main() { let x = 5; // Дефинираме x makes_copy(x); // Тук стойността на x би се преместила във функцията, // но i32 е Copy, затова може да използваме x в последствие. println!("This was a triumph"); println!("x is still alive"); println!("with the value of {}", x); } // Тук x излиза от scope. fn makes_copy(some_integer: i32) { println!("{}", some_integer); } // some_integer излиза от scope, но не се случва нищо особено.
Собственост
Функции които връщат стойност
Връщането на стойност от функция също може да прехвърля собственост
fn main() {
let s1 = gives_ownership();
let s2 = String::from("hello");
let s3 = takes_and_gives_back(s2);
}
fn gives_ownership() -> String {
let some_string = String::from("hello");
some_string // Тук местим стойността към функцията която е извикала gives_ownership
}
fn takes_and_gives_back(a_string: String) -> String {
a_string
}
fn main() { let s1 = gives_ownership(); let s2 = String::from("hello"); let s3 = takes_and_gives_back(s2); } fn gives_ownership() -> String { let some_string = String::from("hello"); some_string // Тук местим стойността към функцията която е извикала gives_ownership } fn takes_and_gives_back(a_string: String) -> String { a_string }
Собственост
Функции
А как може да продължим да използваме стойността след извикването на функцията?
Собственост
Функции
А как може да продължим да използваме стойността след извикването на функцията?
fn main() {
let s1 = String::from("hello");
let (s2, len) = calculate_length(s1);
println!("The length of '{}' is {}.", s2, len);
}
fn calculate_length(s: String) -> (String, usize) {
let length = s.len(); // len() връща дължината на String.
(s, length)
}
The length of 'hello' is 5.
fn main() { let s1 = String::from("hello"); let (s2, len) = calculate_length(s1); println!("The length of '{}' is {}.", s2, len); } fn calculate_length(s: String) -> (String, usize) { let length = s.len(); // len() връща дължината на String. (s, length) }
Собственост и заемане
А какво ако искаме да използваме стойност във функция без да я местим всеки път?
Заемане на стойност (borrowing)
Референции
fn main() {
let s1 = String::from("hello");
let len = calculate_length(&s1);
println!("The length of '{}' is {}.", s1, len);
}
fn calculate_length(s: &String) -> usize {
s.len()
}
The length of 'hello' is 5.
fn main() { let s1 = String::from("hello"); let len = calculate_length(&s1); println!("The length of '{}' is {}.", s1, len); } fn calculate_length(s: &String) -> usize { s.len() }
Референции
Immutable
Референции
Immutable
- тип
&T
Референции
Immutable
- тип
&T
let ref_x = &x;
Референции
Представяне
Референции
Immutable
fn main() {
let s = String::from("hello");
change(&s);
println!("{}", s);
}
fn change(some_string: &String) {
some_string.push_str(", world");
}
Референции
Immutable
fn main() {
let s = String::from("hello");
change(&s);
println!("{}", s);
}
fn change(some_string: &String) {
some_string.push_str(", world");
}
error[E0596]: cannot borrow `*some_string` as mutable, as it is behind a `&` reference --> src/bin/main_7a8d06574d6b81de9d7bcefd13a155afc2a3b55a.rs:8:5 | 7 | fn change(some_string: &String) { | ------- help: consider changing this to be a mutable reference: `&mut String` 8 | some_string.push_str(", world"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `some_string` is a `&` reference, so the data it refers to cannot be borrowed as mutable For more information about this error, try `rustc --explain E0596`. error: could not compile `rust` due to previous error
fn main() { let s = String::from("hello"); change(&s); println!("{}", s); } fn change(some_string: &String) { some_string.push_str(", world"); }
Референции
Мutable
Референции
Мutable
- тип
&mut T
Референции
Мutable
- тип
&mut T
let ref_x = &mut x;
Референции
Мutable
fn main() {
let mut s = String::from("hello");
change(&mut s);
println!("{}", s);
}
fn change(some_string: &mut String) {
some_string.push_str(", world");
}
hello, world
fn main() { let mut s = String::from("hello"); change(&mut s); println!("{}", s); } fn change(some_string: &mut String) { some_string.push_str(", world"); }
Референции
Правила
- референцията винаги сочи към валидна стойност
Референции
Правила
- референцията винаги сочи към валидна стойност
- (съответно) референцията не може да е null
Референции
Валидност
let r;
{
let s = String::from("hello");
r = &s;
}
println!("{}", r);
Референции
Валидност
let r;
{
let s = String::from("hello");
r = &s;
}
println!("{}", r);
error[E0597]: `s` does not live long enough --> src/bin/main_57ddabce60a0b2fc70095675e3a4176d6ec3e3dc.rs:5:9 | 5 | r = &s; | ^^ borrowed value does not live long enough 6 | } | - `s` dropped here while still borrowed 7 | 8 | println!("{}", r); | - borrow later used here For more information about this error, try `rustc --explain E0597`. error: could not compile `rust` due to previous error
fn main() { let r; { let s = String::from("hello"); r = &s; } println!("{}", r); }
Референции
Правила
Референции
Правила
- По едно и също време към една стойност може да съществува само едно от следните:
Референции
Правила
- По едно и също време към една стойност може да съществува само едно от следните:
- точно една mutable референция
Референции
Правила
- По едно и също време към една стойност може да съществува само едно от следните:
- точно една mutable референция
- произволен брой immutable референции
Референции
Правила
- По едно и също време към една стойност може да съществува само едно от следните:
- точно една mutable референция
- произволен брой immutable референции
one mutable XOR many immutable
Borrow checker
let mut s = String::from("hello");
let r1 = &mut s;
let r2 = &mut s;
println!("{}, {}", r1, r2);
Borrow checker
let mut s = String::from("hello");
let r1 = &mut s;
let r2 = &mut s;
println!("{}, {}", r1, r2);
error[E0499]: cannot borrow `s` as mutable more than once at a time --> src/bin/main_5bdec4f559fb3cb8b422d5856bd844f38ad67a0f.rs:5:10 | 4 | let r1 = &mut s; | ------ first mutable borrow occurs here 5 | let r2 = &mut s; | ^^^^^^ second mutable borrow occurs here 6 | 7 | println!("{}, {}", r1, r2); | -- first borrow later used here For more information about this error, try `rustc --explain E0499`. error: could not compile `rust` due to previous error
fn main() { let mut s = String::from("hello"); let r1 = &mut s; let r2 = &mut s; println!("{}, {}", r1, r2); }
Borrow checker
Решение: не ги използвайте заедно
let mut s = String::from("hello");
let r1 = &mut s;
println!("{}", r1);
let r2 = &mut s;
println!("{}", r2);
hello hello
#![allow(unused_variables)] fn main() { let mut s = String::from("hello"); let r1 = &mut s; println!("{}", r1); let r2 = &mut s; println!("{}", r2); }
Borrow checker
За повече яснота за живота на r1:
let mut s = String::from("hello");
{
let r1 = &mut s;
println!("{}", r1);
}
let r2 = &mut s;
println!("{}", r2);
hello hello
fn main() { let mut s = String::from("hello"); { let r1 = &mut s; println!("{}", r1); } let r2 = &mut s; println!("{}", r2); }
Borrow checker
Не можем да преместим стойност докато има референция към нея
let s1 = String::from("hello");
let r = &s1;
let s2 = s1;
println!("{}", r);
error[E0505]: cannot move out of `s1` because it is borrowed --> src/bin/main_81fbc5758c4c34a72422dd0521641f6895111026.rs:5:10 | 3 | let r = &s1; | --- borrow of `s1` occurs here 4 | 5 | let s2 = s1; | ^^ move out of `s1` occurs here 6 | println!("{}", r); | - borrow later used here For more information about this error, try `rustc --explain E0505`. error: could not compile `rust` due to previous error
fn main() { let s1 = String::from("hello"); let r = &s1; let s2 = s1; println!("{}", r); }
Референции
Към скрита (shadowed) променлива
let s = String::from("first");
let r = &s;
let s = String::from("second");
println!("{}", r);
println!("{}", s);
Референции
Към скрита (shadowed) променлива
let s = String::from("first");
let r = &s;
let s = String::from("second");
println!("{}", r);
println!("{}", s);
first second
fn main() { let s = String::from("first"); let r = &s; let s = String::from("second"); println!("{}", r); println!("{}", s); }
Референции
Към скрита (shadowed) променлива
let s = String::from("hello");
let s = &s;
println!("{}", s);
Референции
Към скрита (shadowed) променлива
let s = String::from("hello");
let s = &s;
println!("{}", s);
hello
fn main() { let s = String::from("hello"); let s = &s; println!("{}", s); }
Референции
Към временна стойност
let s = &String::from("hello");
println!("{}", s);
hello
fn main() { let s = &String::from("hello"); println!("{}", s); }
Референции
Към временна стойност
let s = &mut String::from("hello");
println!("{}", s);
hello
fn main() { let s = &mut String::from("hello"); println!("{}", s); }
Референции
mutable → immutable
fn main() {
let mut s = String::from("hello");
let r = &mut s;
greet_cookies(r);
}
fn greet_cookies(greeting: &String) {
println!("{}, cookies", greeting);
}
fn main() { let mut s = String::from("hello"); let r = &mut s; greet_cookies(r); } fn greet_cookies(greeting: &String) { println!("{}, cookies", greeting); }
Референции
mutable → immutable
fn main() {
let mut s = String::from("hello");
let r = &mut s;
greet_cookies(r);
}
fn greet_cookies(greeting: &String) {
println!("{}, cookies", greeting);
}
hello, cookies
fn main() { let mut s = String::from("hello"); let r = &mut s; greet_cookies(r); } fn greet_cookies(greeting: &String) { println!("{}, cookies", greeting); }
Референции
mutable → mutable
fn main() {
let mut s = String::from("mmm");
let r = &mut s;
get_cookies(r);
println!("{}", r);
}
fn get_cookies(s: &mut String) {
s.push_str(", cookies");
}
fn main() { let mut s = String::from("mmm"); let r = &mut s; get_cookies(r); println!("{}", r); } fn get_cookies(s: &mut String) { s.push_str(", cookies"); }
Референции
mutable → mutable
fn main() {
let mut s = String::from("mmm");
let r = &mut s;
get_cookies(r);
println!("{}", r);
}
fn get_cookies(s: &mut String) {
s.push_str(", cookies");
}
mmm, cookies
fn main() { let mut s = String::from("mmm"); let r = &mut s; get_cookies(r); println!("{}", r); } fn get_cookies(s: &mut String) { s.push_str(", cookies"); }
Низове
Литерали
let s: &str = "hello";
fn main() { let s: &str = "hello"; }
Низове
Литерали
let s: &str = "hello";
fn main() { let s: &str = "hello"; }
- Заделя се в статичната памет на програмата
Низове
Литерали
let s: &str = "hello";
fn main() { let s: &str = "hello"; }
- Заделя се в статичната памет на програмата
- Непроменим (immutable)
Низове
Литерали
let s: &str = "hello";
fn main() { let s: &str = "hello"; }
- Заделя се в статичната памет на програмата
- Непроменим (immutable)
- типа
&str
е специалиен вид референция
Низове
Литерали
let s: &str = "hello";
fn main() { let s: &str = "hello"; }
- Заделя се в статичната памет на програмата
- Непроменим (immutable)
- типа
&str
е специалиен вид референция - стойността
"hello"
не се притежава отs
Низове
Литерали
let s: &str = "hello";
fn main() { let s: &str = "hello"; }
- Заделя се в статичната памет на програмата
- Непроменим (immutable)
- типа
&str
е специалиен вид референция - стойността
"hello"
не се притежава отs
- стойността
"hello"
се "притежава" от програмата, защото е статична
Низове
String
let s = String::from("hello");
fn main() { let s = String::from("hello"); }
Низове
String
let s = String::from("hello");
fn main() { let s = String::from("hello"); }
- Заделя се в динамичната памет
Низове
String
let s = String::from("hello");
fn main() { let s = String::from("hello"); }
- Заделя се в динамичната памет
- Може да се променя (mutable)
Низове
String
let s = String::from("hello");
fn main() { let s = String::from("hello"); }
- Заделя се в динамичната памет
- Може да се променя (mutable)
- има собственост над низа
Низове
Slices
Можем да вземем част от низ
let s = String::from("hello, world");
let r1 = &s[..];
let r2 = &r1[1..4];
println!("{}", r2);
ell
#![allow(unused_variables)] fn main() { let s = String::from("hello, world"); let r1 = &s[..]; let r2 = &r1[1..4]; println!("{}", r2); }
Низове
Slices
- какво е
1..4
?
Типа &str
Типа &str
- резен от низ (string slice)
Типа &str
- резен от низ (string slice)
- специален вид референция
Типа &str
- резен от низ (string slice)
- специален вид референция
- репрезентация -
(ptr, len)
Типа &str
- резен от низ (string slice)
- специален вид референция
- репрезентация -
(ptr, len)
my_name: String last_name: &str [––––––––––––] [–––––––] +–––+––––+––––+–––+–––+–––+ stack frame │ • │ 16 │ 13 │ │ • │ 6 │ +–│–+––––+––––+–––+–│–+–––+ │ │ │ +–––––––––+ │ │ │ │ │ [–│––––––– str –––––––––] +–V–+–––+–––+–––+–––+–––+–––+–V–+–––+–––+–––+–––+–––+–––+–––+–––+ heap │ P │ a │ s │ c │ a │ l │ │ P │ r │ e │ c │ h │ t │ │ │ │ +–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+
Типа &mut str
Типа &mut str
- mutable string slice
Типа &mut str
- mutable string slice
- можем да променяме елементите през него
Типа &mut str
- mutable string slice
- можем да променяме елементите през него
- не можем да добавяме и премахваме елементи, защото имаме само референция към памет, която се притежава от някой друг
Вектори
Tипа Vec
let mut v = Vec::new();
v.push(1);
v.push(2);
v.push(3);
println!("{:?}", v);
[1, 2, 3]
#![allow(unused_variables)] fn main() { let mut v = Vec::new(); v.push(1); v.push(2); v.push(3); println!("{:?}", v); }
Вектори
Tипа Vec
let mut v = Vec::new();
v.push(1);
v.push(2);
v.push(3);
println!("{:?}", v);
[1, 2, 3]
#![allow(unused_variables)] fn main() { let mut v = Vec::new(); v.push(1); v.push(2); v.push(3); println!("{:?}", v); }
- динамичен масив
Вектори
Tипа Vec
let mut v = Vec::new();
v.push(1);
v.push(2);
v.push(3);
println!("{:?}", v);
[1, 2, 3]
#![allow(unused_variables)] fn main() { let mut v = Vec::new(); v.push(1); v.push(2); v.push(3); println!("{:?}", v); }
- динамичен масив
- автоматично си разширява капацитета при добавяне на елементи
Вектори
макрото vec!
let v = vec![1, 2, 3];
println!("{:?}", v);
[1, 2, 3]
#![allow(unused_variables)] fn main() { let v = vec![1, 2, 3]; println!("{:?}", v); }
Типа &[T]
Типа &[T]
- резен от масив (slice)
Типа &[T]
- резен от масив (slice)
- аналогично на &str
Типа &[T]
- резен от масив (slice)
- аналогично на &str
- репрезентиран като
(ptr, len)
&[T]
Резен от масив
let arr = [1, 2, 3];
let slice = &arr[..];
println!("{:?}", slice);
[1, 2, 3]
#![allow(unused_variables)] fn main() { let arr = [1, 2, 3]; let slice = &arr[..]; println!("{:?}", slice); }
&[T]
Резен от масив литерал
let slice = &[1, 2, 3];
println!("{:?}", slice);
[1, 2, 3]
#![allow(unused_variables)] fn main() { let slice = &[1, 2, 3]; println!("{:?}", slice); }
&[T]
Резен от вектор
let v = vec![1, 2, 3];
let slice = &v[..];
println!("{:?}", slice);
[1, 2, 3]
#![allow(unused_variables)] fn main() { let v = vec![1, 2, 3]; let slice = &v[..]; println!("{:?}", slice); }