Taşıma Semantiği
Bir atama (assignment), değişkenler arasında sahipliği (ownership) aktarır:
fn main() { let s1 = String::from("Merhaba!"); let s2 = s1; dbg!(s2); // dbg!(s1); }
s1’ins2’ye atanması sahipliği (ownership) aktarır.s1kapsam (scope) dışına çıktığında hiçbir şey olmaz: hiçbir şeye sahip değildir.s2kapsam (scope) dışına çıktığında, dize (string) verisi serbest bırakılır.
s2’ye taşımadan (move) önce:
s2’ye taşıdıktan (move) sonra:
Bir değeri bir fonksiyona geçirdiğinizde, değer fonksiyon parametresine atanır. Bu, sahipliği (ownership) aktarır:
fn say_hello(name: String) { println!("Merhaba {name}") } fn main() { let name = String::from("Ayşe"); say_hello(name); // say_hello(name); }
-
Bunun C++’daki varsayılanların tersi olduğunu belirtin; C++
std::movekullanmadığınız sürece (ve taşıyan yapıcı özel üye fonksiyonu (move constructor) tanımlanmışsa!) değere göre kopyalama yapar. -
Sadece sahiplik (ownership) taşınır. Verinin kendisini işlemek için herhangi bir makine kodunun üretilip üretilmediği bir optimizasyon meselesidir ve bu tür kopyalamalar agresif bir şekilde optimize edilerek kaldırılır.
-
Basit değerler (tamsayılar gibi)
Copyolarak işaretlenebilir (sonraki slaytları inceleyin). -
Rust’ta, klonlamalar (clones) açıktır (
clonekullanarak).
say_hello örneğinde:
say_hello’ya yapılan ilk çağrıyla,mainname’in sahipliğinden (ownership) vazgeçer. Daha sonra,nameartıkmainiçinde kullanılamaz.nameiçin tahsis edilen dinamik bellek (heap),say_hellofonksiyonunun sonunda serbest bırakılacaktır.main,name’i referans olarak (&name) geçirirse vesay_helloparametresinde bir referans kabul ederse sahipliği elinde tutabilir.- Alternatif olarak,
mainilk çağrıdaname’in bir klonunu (name.clone())geçirebilir. - Rust, taşıma (move) semantiğini varsayılan yaparak ve programcıları klonlamaları açık hale getirmeye zorlayarak, C++’a göre istemeden kopya oluşturmayı daha zor hale getirir.
Daha Fazlasını Keşfedin
Modern C++’da Savunmacı Kopyalar
Modern C++ bunu farklı şekilde çözer:
std::string s1 = "Cpp";
std::string s2 = s1; // s1'deki veriyi çoğalt.
s1’den gelen dinamik bellek (heap) verisi kopyalanır ves2kendi bağımsız kopyasını alır.s1ves2kapsam (scope) dışına çıktığında, her biri kendi belleğini serbest bırakır.
Kopyalayan atama’dan (copy-assignment) önce:
Kopyalayan atamadan (copy-assignment) sonra:
Anahtar noktalar:
-
C++, Rust’tan biraz farklı bir seçim yapmıştır.
=veriyi kopyaladığı için, dize (string) verisinin klonlanması gerekir. Aksi takdirde, herhangi bir dize kapsam dışına çıktığında çifte serbest bırakma (double-free) hatası alırdık. -
C++ ayrıca bir değerin ne zaman taşınabileceğini belirtmek için kullanılan
std::move’a sahiptir. Eğer örneks2 = std::move(s1)olsaydı, hiçbir dinamik bellek (heap) tahsisi gerçekleşmezdi. Taşıma işleminden sonra,s1geçerli ancak belirsiz bir durumda olurdu. Rust’tan farklı olarak, programcınıns1’i kullanmaya devam etmesine izin verilir. -
Rust’tan farklı olarak, C++’daki
=kopyalanan veya taşınan türe göre belirlenen keyfi kodları çalıştırabilir.