Ulaşım
- Adres:Batıkent Mh. 8910 Sk. 6. Etap 1H No: 18 Yeni Toki Eyyübiye / Şanlıurfa (Yeni Alım Satım Karşısı)
- Telefon:0 (545) 528 88 93
- eMail: info@alestaweb.com
Rust öğrenmeye başladınız ve "ownership" kavramını (ownership concept) duydunuz ama kafanız karıştı mı? Endişelenmeyin, yalnız değilsiniz! Alesta Web olarak Rust'ın en önemli ama en zorlu kavramı olan ownership'i (ownership is Rust's most important but most challenging concept) basit örneklerle açıklayacağız. Memory safety, borrowing ve lifetimes konularını (memory safety, borrowing and lifetimes topics) adım adım öğreneceksiniz. Bu rehber 2025'te Rust öğrenmek isteyenler için (for those who want to learn Rust in 2025) mükemmel bir başlangıç noktası!
Diğer programlama dillerinde (in other programming languages) memory yönetimi (memory management) iki şekilde yapılır:
| Yaklaşım (Approach) | Diller (Languages) | Artıları (+) | Eksileri (-) |
|---|---|---|---|
| Garbage Collection | Java, Python, JavaScript, Go | Kolay, güvenli (Easy, safe) | Yavaş, öngörülemez pause'lar (Slow, unpredictable pauses) |
| Manuel Memory | C, C++ | Hızlı, kontrol (Fast, control) | Memory leak, segfault, use-after-free |
| Ownership (Rust) | Rust ✅ | Hızlı + Güvenli (Fast + Safe) | Öğrenme eğrisi (Learning curve) |
Alesta Web ekibinin Rust deneyimine göre (according to Alesta Web team's Rust experience): Ownership başta zor görünse de (even though ownership seems difficult at first), bir kere anladığınızda C++'tan daha güvenli ve Python'dan daha hızlı kod yazabilirsiniz (you can write code safer than C++ and faster than Python)!
Ownership, her değerin (every value) bir "sahibi" olduğu (has an "owner") ve bu sahibin değeri kullanma ve temizleme sorumluluğu taşıdığı (responsible for using and cleaning up the value) bir sistemdir. Garbage collector yok, manuel free() yok, ama memory güvenli (but memory safe)!
Rust'ın ownership sistemi 3 basit kurala dayanır (Rust's ownership system is based on 3 simple rules):
let s = String::from("hello");
// 's' değişkeni "hello" String'inin sahibidir
// 's' variable is the owner of the "hello" String
let s1 = String::from("hello");
let s2 = s1; // Sahiplik s1'den s2'ye taşındı (ownership moved)
println!("{}", s1); // ❌ HATA! s1 artık geçersiz (s1 no longer valid)
{
let s = String::from("hello");
// s burada kullanılabilir (s is usable here)
} // s scope dışına çıktı, memory otomatik temizlendi!
// (s went out of scope, memory automatically cleaned!)
// s artık kullanılamaz (s cannot be used anymore)
Alesta Web tavsiyesi: Bu 3 kuralı (these 3 rules) ezberleyin! Rust'ın %90'ı bu kurallar üzerine kurulu (90% of Rust is built on these rules).
Rust'ta bir değeri başka bir değişkene atadığınızda (when you assign a value to another variable), sahiplik "taşınır" (ownership is "moved"):
fn main() {
let s1 = String::from("Alesta Web");
let s2 = s1; // s1'den s2'ye MOVE (MOVE from s1 to s2)
println!("{}", s2); // ✅ Çalışır: "Alesta Web"
println!("{}", s1); // ❌ COMPILE ERROR!
}
// Hata mesajı (Error message):
// error[E0382]: borrow of moved value: `s1`
Neden? Çünkü String heap'te (on the heap) tutulur ve iki pointer'ın aynı memory'yi göstermesi (two pointers pointing to same memory) double-free bug'ına yol açar. Rust bunu engellemek için (to prevent this) ownership'i taşır!
fn main() {
// Integer'lar Copy trait'ine sahip (have Copy trait)
let x = 5;
let y = x;
println!("x: {}, y: {}", x, y); // ✅ İkisi de çalışır! (Both work!)
// String'ler Copy trait'ine sahip DEĞİL (DON'T have Copy trait)
let s1 = String::from("hello");
let s2 = s1;
println!("{}", s1); // ❌ HATA!
}
Basit tipler (simple types) stack'te tutulur ve kopyalanması ucuzdur (copying is cheap), o yüzden Copy yapılır. Karmaşık tipler (complex types) heap'te tutulur, Move yapılır.
alestaweb.com üzerindeki Rust type system rehberimizde daha fazla detay bulabilirsiniz (you can find more details in our Rust type system guide).
Peki sahipliği taşımadan (without transferring ownership) bir değeri kullanmak istersek? İşte burada borrowing (ödünç alma) devreye giriyor!
fn main() {
let s1 = String::from("Alesta Web");
// s1'i ödünç al (borrow s1) ama sahipliği taşıma (but don't take ownership)
let len = calculate_length(&s1);
println!("'{}' uzunluğu: {}", s1, len); // ✅ s1 hala kullanılabilir!
}
fn calculate_length(s: &String) -> usize {
s.len() // Sadece okuma yapıyoruz (just reading)
} // s scope dışı, ama String drop edilmez (s goes out of scope, but String is NOT dropped)
// çünkü sahip değiliz! (because we don't own it!)
&s1 syntax'ı bir "reference" (referans) oluşturur. Reference sahiplik almaz (reference doesn't take ownership), sadece değere erişim sağlar (just provides access to the value).
fn main() {
let s = String::from("hello");
// Aynı anda birden fazla immutable reference OK! ✅
let r1 = &s;
let r2 = &s;
let r3 = &s;
println!("{}, {}, {}", r1, r2, r3); // ✅ Hepsi çalışır!
}
İstediğiniz kadar immutable reference oluşturabilirsiniz (you can create as many immutable references as you want). Sadece okuma yaptıkları için (since they only read) sorun yok!
Kitap ödünç vermek gibi düşünün (think of it like lending a book): Kitabınızı arkadaşınıza verdiniz (&referans), o okuyor ama kitap hala sizin (it's still yours). Arkadaşınız bitirince (reference scope ends) kitap size geri geliyor. Birden fazla kişi aynı kitabı okuyabilir ama hiç kimse sayfaları yırtamaz (no one can tear pages) çünkü immutable!
Eğer ödünç aldığımız değeri değiştirmek istiyorsak (if we want to modify the borrowed value), mutable reference kullanırız:
fn main() {
let mut s = String::from("hello");
change(&mut s); // Mutable reference geçiyoruz (passing mutable reference)
println!("{}", s); // "hello, world!"
}
fn change(s: &mut String) {
s.push_str(", world!"); // String'i değiştiriyoruz! (modifying String!)
}
Dikkat edin: s değişkeni mut olmalı (must be mut) ve &mut s ile mutable reference oluşturuyoruz.
fn main() {
let mut s = String::from("hello");
let r1 = &mut s;
let r2 = &mut s; // ❌ COMPILE ERROR!
println!("{}, {}", r1, r2);
}
// error[E0499]: cannot borrow `s` as mutable more than once at a time
Aynı anda sadece BİR tane mutable reference olabilir (only ONE mutable reference at a time)! Bu data race'i (data race) compile-time'da önler (prevents at compile-time).
fn main() {
let mut s = String::from("hello");
let r1 = &s; // ✅ immutable borrow
let r2 = &s; // ✅ immutable borrow
let r3 = &mut s; // ❌ HATA! Immutable reference varken mutable olamaz
// (Cannot have mutable while immutable exists)
println!("{}, {}, {}", r1, r2, r3);
}
fn main() {
let mut s = String::from("hello");
let r1 = &s;
let r2 = &s;
println!("{} and {}", r1, r2);
// r1 ve r2 artık kullanılmıyor (r1 and r2 no longer used)
let r3 = &mut s; // ✅ ARTIK OK! (NOW OK!)
println!("{}", r3);
}
Alesta Web notu: Rust 2018 edition'dan beri (since Rust 2018 edition), reference'ların son kullanımından sonra (after last use of references) yeni borrow yapabilirsiniz. Bu "Non-Lexical Lifetimes" (NLL) özelliği.
Lifetime, bir reference'ın ne kadar süre geçerli olduğunu (how long a reference is valid) belirtir. Çoğu zaman Rust bunu otomatik çıkarır (Rust infers this automatically most of the time) ama bazen açıkça belirtmeniz gerekir (sometimes you need to specify explicitly).
fn main() {
let r;
{
let x = 5;
r = &x; // ❌ HATA! x scope dışına çıkacak
// (ERROR! x will go out of scope)
}
println!("{}", r); // r artık geçersiz memory'yi gösterir!
// (r would point to invalid memory!)
}
// error[E0597]: `x` does not live long enough
Rust compile-time'da bunu engelliyor (prevents this at compile-time)! C++'ta bu segmentation fault olurdu (this would be a segfault in C++).
// Hangi reference daha uzun yaşıyor? (Which reference lives longer?)
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
fn main() {
let s1 = String::from("Alesta");
let s2 = String::from("Web");
let result = longest(&s1, &s2);
println!("En uzun: {}", result); // "Alesta"
}
'a lifetime parametresi (lifetime parameter), return edilen reference'ın x ve y'den en az biri kadar yaşayacağını (will live at least as long as one of x or y) garanti eder.
Lifetime'lar başlangıçta kafa karıştırıcıdır (lifetimes are confusing at first). Alesta Web tavsiyesi: İlk başta lifetime yazmadan kod yazın (write code without lifetimes at first), compiler hata verirse (if compiler gives error) o zaman lifetime ekleyin. Compiler size tam olarak ne yapmanız gerektiğini söyleyecektir (will tell you exactly what to do)!
fn main() {
let mut numbers = vec![1, 2, 3, 4, 5];
// Immutable borrow - sadece okuma (just reading)
for num in &numbers {
println!("{}", num);
}
// Mutable borrow - değiştirme (modifying)
for num in &mut numbers {
*num *= 2; // Her elemanı 2 ile çarp (multiply each element by 2)
}
println!("{:?}", numbers); // [2, 4, 6, 8, 10]
}
struct User {
name: String,
email: String,
}
fn main() {
let user1 = User {
name: String::from("alestaweb"),
email: String::from("info@alestaweb.com"),
};
// user1'i ödünç al (borrow user1)
print_user(&user1);
// user1 hala kullanılabilir! (user1 still usable!)
println!("User: {}", user1.name);
}
fn print_user(user: &User) {
println!("Name: {}, Email: {}", user.name, user.email);
}
fn main() {
let mut text = String::from("Alesta");
append_web(&mut text);
println!("{}", text); // "Alesta Web"
}
fn append_web(s: &mut String) {
s.push_str(" Web"); // String'e ekleme (appending to String)
}
Alesta Web ekibinin Rust projelerinde (in Rust projects) en çok kullandığı pattern'ler bunlar (these are the most used patterns). alestaweb.com üzerinde daha fazla Rust örneği bulabilirsiniz.
// YANLIŞ (WRONG):
let s1 = String::from("hello");
let s2 = s1;
println!("{}", s1); // HATA!
// DOĞRU (CORRECT):
let s1 = String::from("hello");
let s2 = s1.clone(); // Explicit clone
println!("{}, {}", s1, s2); // ✅ İkisi de çalışır
clone() pahalı bir işlemdir (expensive operation). Mümkünse borrowing kullanın (use borrowing if possible)!
// YANLIŞ (WRONG):
let mut s = String::from("hello");
let r1 = &mut s;
let r2 = &mut s; // HATA!
// DOĞRU (CORRECT):
let mut s = String::from("hello");
{
let r1 = &mut s;
r1.push_str(" world");
} // r1 scope dışı (r1 goes out of scope)
let r2 = &mut s; // ✅ Artık OK!
// YANLIŞ (WRONG):
fn dangle() -> &String {
let s = String::from("hello");
&s // HATA! s drop edilecek (s will be dropped)
}
// DOĞRU (CORRECT):
fn no_dangle() -> String {
let s = String::from("hello");
s // Sahipliği taşı (move ownership)
}
Alesta Web deneyimi: Bu hatalar başlangıçta sıkça yapılır (these errors are frequently made at first) ama Rust compiler çok yardımcıdır (Rust compiler is very helpful). Hata mesajlarını okuyun (read error messages), genelde çözümü gösterir (usually shows the solution)!
Bu makalede kullanılan bilgiler aşağıdaki güvenilir kaynaklardan alınmıştır (information used in this article is from the following reliable sources):
Alesta Web olarak tüm kavramları gerçek Rust projelerinde test ettik ve doğruladık (we tested and verified all concepts in real Rust projects).
Alesta Web olarak size ownership kavramını (ownership concept) basit örneklerle anlattık. Bu Rust'ın temeli (this is the foundation of Rust) ve bir kere anladığınızda her şey çok daha kolay olacak (everything will be much easier once you understand)!
Hızlı Hatırlatıcı / Quick Reminder:
Sonraki Adımlar / Next Steps:
Faydalı Linkler / Useful Links:
Ownership kavramını anlamak Rust öğrenmenin en zor kısmı (understanding ownership is the hardest part of learning Rust). Bunu geçtiniz, artık yolun yarısındasınız! Sorularınız için alestaweb.com üzerinden Alesta Web ekibine ulaşabilirsiniz.
© 2025 AlestaWeb - Tüm hakları saklıdır. Bu rehber Alesta Web tarafından hazırlanmıştır.