Semantyka przenoszenia
An assignment will transfer ownership between variables:
fn main() {
let s1: String = String::from("Hello!");
let s2: String = s1;
println!("s2: {s2}");
// println!("s1: {s1}");
}
- Przypisanie
s1dos2przenosi własność. - When
s1goes out of scope, nothing happens: it does not own anything. - Kiedy zmienna
s2wychodzi poza zakres, dane łańcucha znaków są zwalniane.
Przed przeniesieniem do s2:
Po przeniesieniu do s2:
Kiedy przekazujesz wartość do funkcji, wartość jest przypisywana do parametru funkcji. To przenosi własność:
fn say_hello(name: String) {
println!("Hello {name}")
}
fn main() {
let name = String::from("Alice");
say_hello(name);
// say_hello(name);
}
-
Wspomnij, że jest to na odwrót niż w C++, który domyślnie kopiuje wartości chyba, że jest użyte
std::move(i zdefiniowany konstruktor przenoszenia!). -
It is only the ownership that moves. Whether any machine code is generated to manipulate the data itself is a matter of optimization, and such copies are aggressively optimized away.
-
Simple values (such as integers) can be marked
Copy(see later slides). -
W Ruście, klonowanie jest jawne (za pomocą
clone).
In the say_hello example:
- Przy pierwszym wywołaniu
say_hello,mainoddaje własnośćname. Potemnamenie może być już użyte wewnątrzmain. - Dane zaalokowane na stercie dla
namebędą zwolnione na końcu wywołania funkcjisay_hello. mainmoże zachować własność jeżeli przekażenamejako referencję (&name) i jeżelisay_helloakceptuje referencję jako parameter.- Alternatywnie,
mainmoże przekazać klonanamew pierwszym wywołaniu (name.clone()). - Przez używanie semantyki przenoszenia domyślnie i przez zmuszanie programistów do jawnego tworzenia klonów, Rust powoduje, że przypadkowe tworzenie kopii jest trudniejsze niż w C++.
More to Explore
Defensive Copies in Modern C++
Nowoczesny C++ rozwiązuje to inaczej:
std::string s1 = "Cpp";
std::string s2 = s1; // Duplicate the data in s1.
- Dane sterty z
s1są zduplikowane is2dostaje swoją niezależną kopię. - Kiedy
s1is2wychodzą poza zakres, obydwie zmienne zwalniają swoją pamięć.
Przed przypisywaniem kopiującym:
Po przypisaniu kopiującym:
Kluczowe punkty:
-
C++ has made a slightly different choice than Rust. Because
=copies data, the string data has to be cloned. Otherwise we would get a double-free when either string goes out of scope. -
C++ also has
std::move, which is used to indicate when a value may be moved from. If the example had beens2 = std::move(s1), no heap allocation would take place. After the move,s1would be in a valid but unspecified state. Unlike Rust, the programmer is allowed to keep usings1. -
Unlike Rust,
=in C++ can run arbitrary code as determined by the type which is being copied or moved.