Obsah
1. Ukazatele v Rustu aneb temná strana Síly
2. Deklarace a inicializace proměnné typu ukazatel
3. První demonstrační příklad – deklarace a inicializace ukazatele
4. Přístup k hodnotám proměnných přes ukazatel – blok unsafe
5. Kontrola překladačem na použití bloku unsafe
6. Měnitelné versus neměnitelné ukazatele, měnitelné versus neměnitelné proměnné
7. Ukazatele pro čtení či pro zápis hodnot do referencovaných proměnných
8. Demonstrační příklad – zápis do proměnné přes ukazatel
9. Kontrola, zda je možné do proměnné skutečně zapisovat
10. Krátká rekapitulace – deklarace a inicializace ukazatelů různých typů
11. Čtení či zápis do proměnné mimo oblast její životnosti?
12. Ukazatel na datovou strukturu
13. Přístup k prvkům struktury přes ukazatel
14. Repositář s demonstračními příklady
1. Ukazatele v Rustu aneb temná strana Síly
V programovacím jazyku Rust je možné a v některých případech dokonce i nutné používat ukazatele reprezentované primitivním typem pointer, které se však v některých ohledech liší od „klasických“ ukazatelů známých z jazyků C či C++. Na základě mnohaletých zkušeností vývojářů Rustu se zmíněnými programovacími jazyky C/C++ totiž byly ukazatele v Rustu navrženy takovým způsobem, aby práce s nimi byla poněkud bezpečnější (pokud je to vůbec možné) a aby všechny potenciálně nebezpečné operace byly umístěny do speciálního bloku nazvaného unsafe. Do určité míry se zjednodušila i ukazatelová aritmetika (pointer arithmetic/pointer math) díky existenci funkce pointer.offset(). I tak je však při práci s ukazateli nutné dbát zvýšené opatrnosti, protože překladač například nehlídá to, jestli ukazatel obsahuje adresu stále živé proměnné atd.
V praxi se většinou snažíme se použití ukazatelů zcela vyhnout, samozřejmě za předpokladu, že je to možné. Mnoho programů vytvořených v Rustu ukazatele vůbec nepoužívá.
Poznámka: v minulosti existovalo v Rustu několik typů ukazatelů, navíc je slovo pointer dodnes používáno v několika kontextech. Ukazatele popisované dnes spadají do kategorie „raw pointers“.
2. Deklarace a inicializace proměnné typu ukazatel
V programovacím jazyku Rust rozeznáváme dva typy „raw“ ukazatelů – ukazatele používané pro čtení konstantní i měnitelné hodnoty a ukazatele na hodnoty, které lze přes ukazatel změnit (mutable). Nejdříve se seznámíme s ukazateli používanými jen pro čtení hodnoty (read only). Jejich typ je vždy *const T, kde T je prakticky libovolný datový typ Rustu. Pokud například budeme chtít nadefinovat proměnnou nazvanou pointer, která je ukazatelem na konstantní či měnitelnou 32bitovou celou hodnotu se znaménkem, bude deklarace vypadat následovně:
let pointer: *const i32;
Přiřazení adresy do ukazatele se do značné míry podobá zápisu používaném v céčku nebo i v Rustu při získávání reference:
let value: i32 = 42; pointer = &value;
Deklaraci ukazatele můžeme spojit s jeho inicializací:
let value: i32 = 42; let pointer: *const i32 = &value;
Poznámka: v tomto případě ovšem vždy musíte explicitně uvést datový typ ukazatele, jinak by se vytvořila „pouze“ reference na hodnotu (což již známe). Následující kód má tedy odlišný význam:
let value: i32 = 42; let reference = &value;
Popř. explicitně:
let value: i32 = 42; let reference: &i32 = &value;
Poznámka: interně se reference a ukazatele vlastně neliší, protože obsahují stejnou hodnotu = adresu proměnné. Práce s nimi je však odlišná, stejně jako kontroly, které provádí překladač.
3. První demonstrační příklad – deklarace a inicializace ukazatele
V dnešním prvním demonstračním příkladu vytvoříme neměnitelnou (immutable) proměnnou nazvanou value, k ní získáme referenci a taktéž ukazatel na ni. Následně je na standardní výstup vypsána hodnota proměnné, hodnota téže proměnné, ale přes referenci a konečně též obsah samotného ukazatele. Ovšem ukazatel obsahuje adresu proměnné, takže třetí řádek nevypíše 42, ale hexadecimální adresu value umístěné na zásobníkovém rámci funkce main (u reference se naproti tomu automaticky provede dereference a tudíž přečtení hodnoty proměnné). Povšimněte si, že získání reference na proměnnou a adresy proměnné se zapisuje stejným znakem &, jediný rozdíl spočívá v odlišném datovém typu:
fn main() { let value: i32 = 42; let reference: &i32 = &value; let pointer: *const i32 = &value; println!("{}", value); println!("{}", reference); println!("{:?}", pointer); }
Po spuštění může tento příklad vypsat například následující hodnoty. Adresa proměnné value (tedy hodnota ukazatele) se samozřejmě může ve vašem případě lišit:
42 42 0x7fffc7039394
4. Přístup k hodnotám proměnných přes ukazatel – blok unsafe
K hodnotám proměnných lze samozřejmě přistupovat i přes ukazatel (jinak by ostatně nemělo smysl s ukazateli pracovat). Zápis je v tomto případě prakticky stejný, jak ho známe z céčka či z C++:
*ukazatel
Velký rozdíl mezi Rustem na jedné straně a jazyky C/C++ na straně druhé však spočívá v tom, že přístup přes ukazatel je považován za potenciálně nebezpečnou operaci a musí být za všech okolností uzavřen do speciálního bloku unsafe:
unsafe { ... *ukazatel ... }
Podívejme se nyní na druhý demonstrační příklad, který na posledním řádku vypíše hodnotu proměnné získané nepřímo přes ukazatel:
fn main() { let value: i32 = 42; let reference: &i32 = &value; let pointer: *const i32 = &value; println!("{}", value); println!("{}", reference); println!("{:?}", pointer); unsafe { println!("{}", *pointer); } }
Příklad výstupu tohoto demonstračního příkladu (třetí řádek se opět pravděpodobně bude na vašem počítači lišit):
42 42 0x7fff56270904 42
Alternativně je možné příklad přepsat takto (vložením bloku unsafe dovnitř makra println!):
fn main() { let value: i32 = 42; let reference: &i32 = &value; let pointer: *const i32 = &value; println!("{}", value); println!("{}", reference); println!("{:?}", pointer); println!("{}", unsafe {*pointer}); }
5. Kontrola překladačem na použití bloku unsafe
Ve chvíli, kdy blok unsafe nepoužijeme, bude se na nás překladač zlobit. Ostatně si to můžeme velmi snadno vyzkoušet na nepatrně upraveném příkladu, tentokrát ovšem bez unsafe bloku:
fn main() { let value: i32 = 42; let reference: &i32 = &value; let pointer: *const i32 = &value; println!("{}", value); println!("{}", reference); println!("{:?}", pointer); println!("{}", *pointer); }
Překladač skutečně při pokusu o vytvoření binárního spustitelného souboru vypíše chybové hlášení:
--> pointers02_no_unsafe.rs:11:20 | 11 | println!("{}", *pointer); | ^^^^^^^^ unsafe call requires unsafe function or block <std macros>:2:27: 2:58 note: in this expansion of format_args! <std macros>:3:1: 3:54 note: in this expansion of print! (defined in <std macros>) pointers02_no_unsafe.rs:11:5: 11:30 note: in this expansion of println! (defined in <std macros>) error: aborting due to previous error
Podobně je tomu i u dalších potenciálně nebezpečných operací, tj. u většiny operací s ukazateli.
6. Měnitelné versus neměnitelné ukazatele, měnitelné versus neměnitelné proměnné
Vzhledem k tomu, že ukazatele jsou primitivním datovým typem, rozeznává Rust měnitelné a neměnitelné ukazatele. Ovšem je rozdíl například mezi ukazatelem na měnitelnou hodnotu a měnitelným ukazatelem (a aby toho nebylo málo, rozeznáváme ještě typy *const a *mut popsané v navazujících kapitolách). Podívejme se nyní na jednotlivé varianty.
Neměnitelný ukazatel na neměnitelnou hodnotu – ten již známe z předchozích kapitol. Samotnou hodnotu nelze změnit, ovšem ani ukazatel nelze „přesměrovat“ na jinou proměnnou. Jediná povolená operace s ukazatelem je přečtení hodnoty proměnné přes její adresu (tj. dereferencování) v bloku unsafe:
fn main() { let value: i32 = 42; let pointer: *const i32 = &value; println!("{}", value); println!("{:?}", pointer); }
Neměnitelný ukazatel na měnitelnou hodnotu. Samotný ukazatel vždy ukazuje na jedinou proměnnou, jejíž hodnota se však může změnit. Tento ukazatel lze ovšem použít pouze pro čtení hodnoty proměnné, nikoli pro zápis (což je velmi rozumné, jinými slovy kde to jde používejte *const a nikoli dále popsaný *mut):
fn main() { let mut value: i32 = 42; let pointer: *const i32 = &value; println!("{}", value); println!("{:?}", pointer); unsafe { println!("{}", *pointer); } value = 100; println!("{}", value); println!("{:?}", pointer); unsafe { println!("{}", *pointer); } }
Měnitelný ukazatel na neměnitelnou (konstantní) hodnotu. Nyní jedna proměnná pointer v první části programu obsahuje adresu proměnné value1, v další části pak adresu proměnné value2. Jinými slovy adresa uložena v proměnné pointer se sice může změnit, nikoli však hodnoty uložené na této adrese:
fn main() { let value1: i32 = 42; let value2: i32 = 100; let mut pointer: *const i32; println!("{}", value1); pointer = &value1; println!("{:?}", pointer); println!("{}", unsafe {*pointer}); pointer = &value2; println!("{:?}", pointer); println!("{}", unsafe {*pointer}); }
Měnitelný je ukazatel i samotná hodnota. Kombinace předchozích dvou příkladů (stále však platí, že přes ukazatel je možné proměnnou pouze číst, protože typ ukazatele je *const i32):
fn main() { let mut value1: i32 = 1; let mut value2: i32 = 3; let mut pointer: *const i32; pointer = &value1; println!("{}", unsafe {*pointer}); value1 = 2; println!("{}", unsafe {*pointer}); pointer = &value2; println!("{}", unsafe {*pointer}); value2 = 4; println!("{}", unsafe {*pointer}); }
7. Ukazatele pro čtení či pro zápis hodnot do referencovaných proměnných
Aby toho nebylo málo, má klíčové slovo mut ještě jeden význam. Odlišujeme jím totiž ukazatele používané pouze pro čtení a ukazatele, přes něž můžeme měnit (mutovat) proměnnou, na níž ukazují. Prakticky to znamená, že se striktně rozlišuje mezi těmito typy:
let pointer1: *const i32 = &value; let pointer2: *mut i32 = &mut value;
Pokud se použije druhý zápis, musí být i samotná proměnná měnitelná! Tím je zajištěno, že se nikdo nebude snažit modifikovat immutable hodnotu (tedy snažit se může, ale překladač mu to nedovolí).
8. Demonstrační příklad – zápis do proměnné přes ukazatel
Rozdíl spočívá v tom, že ve druhém případě můžeme do proměnné zapisovat přes ukazatel. Podívejme se nyní na demonstrační příklad, z něhož je patrné, že i zápis přes ukazatel je – pochopitelně – potenciálně nebezpečná operace, která musí být uzavřena do bloku unsafe:
fn main() { let mut value: i32 = 42; let pointer: *mut i32 = &mut value; println!("{}", value); unsafe { println!("{}", *pointer); } value = 1; println!("{}", value); unsafe { println!("{}", *pointer); } unsafe { *pointer = 20; } println!("{}", value); unsafe { println!("{}", *pointer); } }
Po překladu a spuštění tohoto příkladu dostaneme tento výstup:
42 42 1 1 20 20
9. Kontrola, zda je možné do proměnné skutečně zapisovat
Opět platí, že si překladač hlídá, zda se ukazatel typu *mut skutečně vytváří pro měnitelnou proměnnou. Zkusme na první modifikátor mut zapomenout:
fn main() { letmutvalue: i32 = 42; let pointer: *mut i32 = &mut value; println!("{}", value); unsafe { println!("{}", *pointer); } value = 1; println!("{}", value); unsafe { println!("{}", *pointer); } unsafe { *pointer = 20; } println!("{}", value); unsafe { println!("{}", *pointer); } }
Překladač v takovém případě vypíše chybové hlášení, jehož druhou část již známe:
error: cannot borrow immutable local variable `value` as mutable --> pointers04_immut_var.rs:4:34 | 2 | let value: i32 = 42; | ----- use `mut value` here to make mutable 3 | 4 | let pointer: *mut i32 = &mut value; | ^^^^^ cannot borrow mutably error[E0384]: re-assignment of immutable variable `value` --> pointers04_immut_var.rs:11:5 | 2 | let value: i32 = 42; | ----- first assignment to `value` ... 11 | value = 1; | ^^^^^^^^^ re-assignment of immutable variable error: aborting due to 2 previous errors
10. Krátká rekapitulace – deklarace a inicializace ukazatelů různých typů
Prozatím jsme se setkali se dvěma způsoby deklarace proměnných – immutable (výchozí volba) a mutable. U ukazatelů taktéž existují varianty, přičemž klíčovými slovy const/mut se určuje, zda se přes ukazatel může do proměnné zapisovat či nikoli. Další varianty určují, zda i samotný ukazatel je immutable či mutable, tj. zde se může ukazatel změnit. Povšimněte si, že dvě možnosti jsou chybné – pokus o vytvoření ukazatele typu *mut na neměnitelnou proměnnou:
Proměnná | Ukazatel | Čtení proměnné | Zápis do proměnné | Čtení přes ukazatel | Zápis přes ukazatel | Ukazatel lze změnit |
---|---|---|---|---|---|---|
let v: i32; | let p: *const i32; | ano | ne | ano | ne | ne |
let v: i32; | let mut p: *const i32; | ano | ne | ano | ne | ano |
let v: i32; | let p: *mut i32; | ano | ne | chyba | chyba | chyba |
let v: i32; | let mut p: *mut i32; | ano | ne | chyba | chyba | chyba |
let mut v: i32; | let p: *const i32; | ano | ano | ano | ne | ne |
let mut v: i32; | let mut p: *const i32; | ano | ano | ano | ne | ano |
let mut v: i32; | let p: *mut i32; | ano | ano | ano | ano | ne |
let mut v: i32; | let mut p: *mut i32; | ano | ano | ano | ano | ano |
11. Čtení či zápis do proměnné mimo oblast její životnosti?
Programovací jazyk Rust (resp. přesněji řečeno jeho překladač) sice hlídá mnoho operací prováděných s ukazateli, ovšem nedokáže (a pravděpodobně to ani není prakticky možné) určit, zda ukazatel ještě obsahuje adresu živé proměnné či zda se již proměnná nachází mimo oblast své platnosti. Proto je možné přeložit následující program, který může (ale také nemusí) fungovat, protože v poslední části přistupujeme přes ukazatel k proměnné mimo oblast její viditelnosti:
fn main() { let pointer: *mut i32; { let mut value: i32 = 42; pointer = &mut value; println!("{}", value); unsafe { println!("{}", *pointer); } value = 1; println!("{}", value); unsafe { println!("{}", *pointer); } unsafe { *pointer = 20; } println!("{}", value); unsafe { println!("{}", *pointer); } } // !!! unsafe { *pointer = 99; println!("{}", *pointer); } }
Poznámka: toto je asi největší praktický rozdíl mezi referencemi a ukazateli.
12. Ukazatel na datovou strukturu
Ukazatel samozřejmě nemusí obsahovat jen adresu primitivní proměnné, ale i adresu datové struktury. Opět se na chvíli vraťme k naší struktuře s komplexními čísly, jejíž nejjednodušší varianta vypadá takto:
#[derive(Debug)] struct Complex { real: f32, imag: f32, } impl Complex { fn new(real: f32, imag: f32) -> Complex { println!("Constructing complex number: {:}+{:}i", real, imag); Complex{real:real, imag:imag} } }
Nyní si můžeme vytvořit novou proměnnou typu Complex, deklarovat ukazatel na tuto datovou strukturu a naplnit ho. Pro zajímavost bude struktura měnitelná a tudíž si můžeme dovolit vytvořit i ukazatel typu *mut:
let mut value: Complex = Complex::new(1.0, 2.0); let pointer: *mut Complex; pointer = &mut value;
13. Přístup k prvkům struktury přes ukazatel
Změna složek datové struktury přímo (přes příslušnou proměnnou) je triviální:
value.real = 10.0; value.imag = 20.0;
Totéž lze provést nepřímo přes ukazatel. Závorky pro dereferenci jsou nutné:
unsafe { (*pointer).real = 20.0; (*pointer).imag = 40.0; }
Poznámka: kupodivu zde nelze použít operátor ->, což je škoda, protože mi připadá mnohem čitelnější.
Celý příklad, v němž se použije ukazatel na strukturu typu Complex, může vypadat takto:
#[derive(Debug)] struct Complex { real: f32, imag: f32, } impl Complex { fn new(real: f32, imag: f32) -> Complex { println!("Constructing complex number: {:}+{:}i", real, imag); Complex{real:real, imag:imag} } } fn main() { let mut value: Complex = Complex::new(1.0, 2.0); let pointer: *mut Complex; pointer = &mut value; println!("{:?}", value); unsafe { println!("{:?}", *pointer); } value.real = 10.0; value.imag = 20.0; println!("{:?}", value); unsafe { println!("{:?}", *pointer); } unsafe { (*pointer).real = 20.0; (*pointer).imag = 40.0; } println!("{:?}", value); unsafe { println!("{:?}", *pointer); } }
14. Repositář s demonstračními příklady
Všechny dnes popisované demonstrační příklady byly, ostatně podobně jako ve všech předchozích částech tohoto seriálu, uloženy do Git repositáře dostupného na adrese https://github.com/tisnik/presentations. Příklady si můžete v případě potřeby stáhnout i jednotlivě bez nutnosti klonovat celý repositář:
Příklad | Adresa |
---|---|
pointers01.rs | https://github.com/tisnik/presentations/blob/master/rust/pointers/pointers01.rs |
pointers02.rs | https://github.com/tisnik/presentations/blob/master/rust/pointers/pointers02.rs |
pointers02_inner_unsafe.rs | https://github.com/tisnik/presentations/blob/master/rust/pointers/pointers02_inner_unsafe.rs |
pointers02_no_unsafe.rs | https://github.com/tisnik/presentations/blob/master/rust/pointers/pointers02_no_unsafe.rs |
pointers03.rs | https://github.com/tisnik/presentations/blob/master/rust/pointers/pointers03.rs |
pointers03_mut_all.rs | https://github.com/tisnik/presentations/blob/master/rust/pointers/pointers03_mut_all.rs |
pointers03_mut_pointer.rs | https://github.com/tisnik/presentations/blob/master/rust/pointers/pointers03_mut_pointer.rs |
pointers04.rs | https://github.com/tisnik/presentations/blob/master/rust/pointers/pointers04.rs |
pointers04_immut_var.rs | https://github.com/tisnik/presentations/blob/master/rust/pointers/pointers04_immut_var.rs |
Další příklady byly připraveny pro navazující část tohoto seriálu, takže jen pro úplnost:
15. Odkazy na Internetu
- Primitive Type pointer
https://doc.rust-lang.org/std/primitive.pointer.html - Cargo: správce projektů a balíčků pro programovací jazyk Rust
https://mojefedora.cz/cargo-spravce-projektu-a-balicku-pro-programovaci-jazyk-rust/ - Network Communication and Serialization in Rust
https://www.safaribooksonline.com/blog/2014/01/28/network-communication-serialization-rust/ - Crate bincode
http://tyoverby.com/bincode/bincode/index.html - Struct std::fs::File
https://doc.rust-lang.org/std/fs/struct.File.html - Trait std::io::Seek
https://doc.rust-lang.org/std/io/trait.Seek.html - Trait std::io::Read
https://doc.rust-lang.org/std/io/trait.Read.html - Trait std::io::Write
https://doc.rust-lang.org/std/io/trait.Write.html - Trait std::io::BufRead
https://doc.rust-lang.org/std/io/trait.BufRead.html - Module std::io::prelude
https://doc.rust-lang.org/std/io/prelude/index.html - std::net::IpAddr
https://doc.rust-lang.org/std/net/enum.IpAddr.html - std::net::Ipv4Addr
https://doc.rust-lang.org/std/net/struct.Ipv4Addr.html - std::net::Ipv6Addr
https://doc.rust-lang.org/std/net/struct.Ipv6Addr.html - TcpListener
https://doc.rust-lang.org/std/net/struct.TcpListener.html - TcpStream
https://doc.rust-lang.org/std/net/struct.TcpStream.html - Binary heap (Wikipedia)
https://en.wikipedia.org/wiki/Binary_heap - Binární halda (Wikipedia)
https://cs.wikipedia.org/wiki/Bin%C3%A1rn%C3%AD_halda - Halda (datová struktura)
https://cs.wikipedia.org/wiki/Halda_%28datov%C3%A1_struktura%29 - Struct std::collections::HashSet
https://doc.rust-lang.org/std/collections/struct.HashSet.html - Struct std::collections::BTreeSet
https://doc.rust-lang.org/std/collections/struct.BTreeSet.html - Struct std::collections::BinaryHeap
https://doc.rust-lang.org/std/collections/struct.BinaryHeap.html - Set (abstract data type)
https://en.wikipedia.org/wiki/Set_%28abstract_data_type%29#Language_support - Associative array
https://en.wikipedia.org/wiki/Associative_array - Hash Table
https://en.wikipedia.org/wiki/Hash_table - B-tree
https://en.wikipedia.org/wiki/B-tree - Pedro Celis: Robin Hood Hashing (naskenované PDF!)
https://cs.uwaterloo.ca/research/tr/1986/CS-86–14.pdf - Robin Hood hashing
http://codecapsule.com/2013/11/11/robin-hood-hashing/ - Robin Hood hashing: backward shift deletion
http://codecapsule.com/2013/11/17/robin-hood-hashing-backward-shift-deletion/ - Module std::collections
https://doc.rust-lang.org/std/collections/ - Module std::vec
https://doc.rust-lang.org/nightly/std/vec/index.html - Struct std::collections::VecDeque
https://doc.rust-lang.org/std/collections/struct.VecDeque.html - Struct std::collections::LinkedList
https://doc.rust-lang.org/std/collections/struct.LinkedList.html - Module std::fmt
https://doc.rust-lang.org/std/fmt/ - Macro std::println
https://doc.rust-lang.org/std/macro.println.html - Enum std::result::Result
https://doc.rust-lang.org/std/result/enum.Result.html - Module std::result
https://doc.rust-lang.org/std/result/ - Result
http://rustbyexample.com/std/result.html - Rust stdlib: Option
https://doc.rust-lang.org/std/option/enum.Option.html - Module std::option
https://doc.rust-lang.org/std/option/index.html - Rust by example: option
http://rustbyexample.com/std/option.html - Rust by example: if-let
http://rustbyexample.com/flow_control/if_let.html - Rust by example: while let
http://rustbyexample.com/flow_control/while_let.html - Rust by example: Option<i32>
http://rustbyexample.com/std/option.html - An Overview of Macros in Rust
http://words.steveklabnik.com/an-overview-of-macros-in-rust - A Practical Intro to Macros in Rust 1.0
https://danielkeep.github.io/practical-intro-to-macros.html - The Rust Programming Language: macros
https://doc.rust-lang.org/beta/book/macros.html - Rust by example: 15 macro_rules!
http://rustbyexample.com/macros.html - Primitive Type isize
https://doc.rust-lang.org/nightly/std/primitive.isize.html - Primitive Type usize
https://doc.rust-lang.org/nightly/std/primitive.usize.html - Primitive Type array
https://doc.rust-lang.org/nightly/std/primitive.array.html - Module std::slice
https://doc.rust-lang.org/nightly/std/slice/ - Rust by Example: 2.3 Arrays and Slices
http://rustbyexample.com/primitives/array.html - What is the difference between Slice and Array (stackoverflow)
http://stackoverflow.com/questions/30794235/what-is-the-difference-between-slice-and-array - Learning Rust With Entirely Too Many Linked Lists
http://cglab.ca/~abeinges/blah/too-many-lists/book/ - Testcase: linked list
http://rustbyexample.com/custom_types/enum/testcase_linked_list.html - Operators and Overloading
https://doc.rust-lang.org/book/operators-and-overloading.html - Module std::ops
https://doc.rust-lang.org/std/ops/index.html - Module std::cmp
https://doc.rust-lang.org/std/cmp/index.html - Trait std::ops::Add
https://doc.rust-lang.org/stable/std/ops/trait.Add.html - Trait std::ops::AddAssign
https://doc.rust-lang.org/std/ops/trait.AddAssign.html - Trait std::ops::Drop
https://doc.rust-lang.org/std/ops/trait.Drop.html - Trait std::cmp::Eq
https://doc.rust-lang.org/std/cmp/trait.Eq.html - Struct std::boxed::Box
https://doc.rust-lang.org/std/boxed/struct.Box.html - Explore the ownership system in Rust
https://nercury.github.io/rust/guide/2015/01/19/ownership.html - Rust's ownership and move semantic
http://www.slideshare.net/saneyuki/rusts-ownership-and-move-semantics - Trait std::marker::Copy
https://doc.rust-lang.org/stable/std/marker/trait.Copy.html - Trait std::clone::Clone
https://doc.rust-lang.org/stable/std/clone/trait.Clone.html - The Stack and the Heap
https://doc.rust-lang.org/book/the-stack-and-the-heap.html - Rust Compare: Pointers & References
http://www.rust-compare.com/site/pointers.html - Rust Compare: Parameters
http://www.rust-compare.com/site/params.html - Why does this compile? Automatic dereferencing?
https://users.rust-lang.org/t/why-does-this-compile-automatic-dereferencing/2183 - Understanding Pointers, Ownership, and Lifetimes in Rust
http://koerbitz.me/posts/Understanding-Pointers-Ownership-and-Lifetimes-in-Rust.html - Rust lang series episode #25 — pointers (#rust-series)
https://steemit.com/rust-series/@jimmco/rust-lang-series-episode-25-pointers-rust-series - Rust – home page
https://www.rust-lang.org/en-US/ - Rust – Frequently Asked Questions
https://www.rust-lang.org/en-US/faq.html - Destructuring and Pattern Matching
https://pzol.github.io/getting_rusty/posts/20140417_destructuring_in_rust/ - The Rust Programming Language
https://doc.rust-lang.org/book/ - Rust (programming language)
https://en.wikipedia.org/wiki/Rust_%28programming_language%29 - Go – home page
https://golang.org/ - Stack Overflow – Most Loved, Dreaded, and Wanted language
https://stackoverflow.com/research/developer-survey-2016#technology-most-loved-dreaded-and-wanted - Rust vs Go (dva roky staré hodnocení, od té doby došlo k posunům v obou jazycích)
http://jaredforsyth.com/2014/03/22/rust-vs-go/ - Rust vs Go: My experience
https://www.reddit.com/r/golang/comments/21m6jq/rust_vs_go_my_experience/ - Friends of Rust (Organizations running Rust in production)
https://www.rust-lang.org/en-US/friends.html - Rust programs versus C++ g++
https://benchmarksgame.alioth.debian.org/u64q/compare.php?lang=rust&lang2=gpp - Další benchmarky (nejedná se o reálné příklady „ze života“)
https://github.com/kostya/benchmarks - Go na Redditu
https://www.reddit.com/r/golang/ - Rust vs. Go
http://vschart.com/compare/rust/vs/go-language - Abstraction without overhead: traits in Rust
https://blog.rust-lang.org/2015/05/11/traits.html - Method Syntax
https://doc.rust-lang.org/book/method-syntax.html - Traits in Rust
https://doc.rust-lang.org/book/traits.html - Functional Programming in Rust – Part 1 : Function Abstraction
http://blog.madhukaraphatak.com/functional-programming-in-rust-part-1/ - Of the emerging systems languages Rust, D, Go and Nim, which is the strongest language and why?
https://www.quora.com/Of-the-emerging-systems-languages-Rust-D-Go-and-Nim-which-is-the-strongest-language-and-why - Chytré ukazatele (moderní verze jazyka C++) [MSDN]
https://msdn.microsoft.com/cs-cz/library/hh279674.aspx - UTF-8 Everywhere
http://utf8everywhere.org/ - Rust by Example
http://rustbyexample.com/ - Rust oficiálně ve Fedoře
https://mojefedora.cz/rust-oficialne-ve-fedore/ - Resource acquisition is initialization
https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization - TIOBE index (nejnovější data)
http://www.tiobe.com/tiobe-index/ - Porovnání Go, D a Rustu na OpenHubu:
https://www.openhub.net/languages/compare?language_name[]=-1&language_name[]=-1&language_name[]=dmd&language_name[]=golang&language_name[]=rust&language_name[]=-1&measure=commits - String Types in Rust
http://www.suspectsemantics.com/blog/2016/03/27/string-types-in-rust/ - Trait (computer programming)
https://en.wikipedia.org/wiki/Trait_%28computer_programming%29 - Type inference
https://en.wikipedia.org/wiki/Type_inference