---
title: 'Yığıt ve Öbek'
source: 'https://academia.sh/tr/kurslar/sahiplik/yigit-ve-obek'
course: 'Sahiplik ve Bellek Modeli'
language: tr
updated: '2026-09-13T05:09:25+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Dört sınıfı (kapsam sonu, taşındığı yerde, açık çağrıda, kabıyla birlikte) tanımlar ve birbirinden ayırır'
    - 'Ölçüm çekirdeğini koşturarak on dört değerin 6/3/1/4 dağılımını doğrular'
    - 'Kapsam sonunda biten değerlerin bitiş sırasının bildirim sırasının tersi olduğunu koşturarak gösterir'
---

# Yığıt ve Öbek

On dört değerlik bir ölçüm çekirdeği koşturulur ve her değerin ömrünü dört sınıftan birine yerleştirir — kapsam sonu, taşındığı yerde, açık çağrıda, kabıyla birlikte; sonuç 6/3/1/4 olarak sabittir. Kapsam sonunda biten değerlerin bitiş sırasının bildirim sırasının tam tersi olduğu ve öbeğe alınan bir değerin de aynı deftere düştüğü ölçülür.

Önceki kurs kaynakta yazılan bir satırın ne ürettiğini ölçtü: ifade, deyim, öğe. Bu üçlü
sınıflandırma bir satırın çalıştırıldığı anda ne olduğunu belirliyordu, ama bilerek sormadığı
bir soru kaldı — o satırın ürettiği değer ne kadar yaşıyor. Bu kurs tam oraya bakıyor ve
bütün dersleri boyunca tek bir soru soruluyor: bu değerin ömrü nerede bitiyor?

Bu soru daha önce farklı bir bağlamda karşımıza çıkmıştı. Eşzamanlılık kursu (M09/K03) bir
goroutine'in nasıl duracağını ölçtü — koşan bir birimin sonlanması. Bu kurs aynı fiili farklı
bir özneye uyguluyor: orada koşan bir birim duruyordu, burada bir değer bitiyor. Bir birimin
durması dışarıdan bir kararla (kanal kapanması, bağlam iptali) tetiklenirken, bir değerin
bitişi kaynağın kendi yapısından okunabiliyor — ayrı bir karar mekanizmasına ihtiyaç
duymadan.

## Dört Yanıt

Rust'ta bir değerin ömrü dört biçimden birinde bitiyor ve kurs boyunca bu dört ad
değişmiyor.

| Sınıf | Tanım |
|---|---|
| kapsam sonu | Değer, bağlandığı bloğun sonunda biter |
| taşındığı yerde | Sahiplik başkasına geçti; ömür yeni sahibin bittiği yerde biter |
| açık çağrıda | Kaynakta yazılı bir çağrı ömrü erken bitirir |
| kabıyla birlikte | Değer bir kabın içindedir; kap bitince o da biter |

Bu dört sınıf birbirini dışlıyor: bir değer aynı anda hem kapsam sonunda hem taşındığı
yerde bitemez, çünkü taşınan bir değerin eski bağlaması zaten canlı değil — bitiş, bir
değerin hayatında yalnız bir kez, dört yoldan tam biriyle gerçekleşiyor. Bitiş noktası
kaynağın kendi yapısından okunuyor ve bir çalışma zamanı kararına bağlı değil; bu yüzden
ölçüm bir süre ya da bir sayaç değil, sıralı bir kayıt üretiyor — hangi değerin ne zaman
bittiğinin listesi.

Programlama Temelleri kursu (M01/K02) kapsam (scope) kavramını zaten kurmuştu: bir adın
hangi blokta göründüğü ve o bloktan çıkınca adın erişilemez hâle geldiği. Bu kurs aynı
kavramı tekrar tanımlamıyor; pay, Rust'ın kapsamı yalnız bir görünürlük sınırı olarak değil,
bir **bitiş noktası** olarak da kullanmasında. Bir adın kapsam dışına çıkması, çoğu dilde
yalnız o ada bir daha erişilemeyeceği anlamına gelir; burada aynı olay, adın tuttuğu değerin
de sonlandığı anlamına geliyor — ve bu sonlanma, derleme zamanında bilinen bir noktada,
çalışma zamanında kesin olarak gerçekleşiyor.

## Ölçüm Çekirdeği

Kursun geri kalanında kullanılan çekirdek `omur.rs`'dir. On dört ayrı değer dört bölüm
halinde (A, B, C, D) oluşturuluyor, her değerin bitişi ortak bir gözlem defterine
yazılıyor ve sonunda sınıf başına toplam basılıyor.

Her bölüm kendi ölçümünü aynı yöntemle alıyor: bölüm başlamadan önce defterin o anki
uzunluğu (`a0`, `b0`, `c0`, `d0`) kaydediliyor, bölümün kapsamı kapandıktan sonra
`yeni_olanlar` işlevi yalnız o uzunluktan sonra eklenen satırları döndürüyor. Bu, dört
bölümün birbirinin ölçümüne karışmasını engelliyor — A bölümünde biten üç değer, B
bölümünün ölçümünde bir daha görünmüyor, çünkü B'nin başlangıç noktası zaten A bittikten
sonraki uzunluğu alıyor. Aynı defter dördü için de ortak, ama her bölüm kendi payını
kendi başlangıç noktasından itibaren okuyor.

Gözlem defteri `Defter` tipiyle tutuluyor — birden çok `Iz` örneğinin aynı listeye
yazabilmesini sağlayan paylaşılan bir kayıt. Bu paylaşımın kendi iç yapısı
(`Rc<RefCell<Vec<String>>>`) ölçüm aracının bir tasarım kararıdır; nasıl çalıştığı Referans
Sayımı ve İç Değişebilirlik derslerinde ayrı birer konu olarak ele alınacak. Burada önemli
olan yalnız şu: her `Iz` değeri `Drop` trait'ini uyguluyor, yani bir değerin ömrü bittiğinde
derleyici otomatik olarak bir kapanış kodu çalıştırıyor ve bu kod kendi adını deftere
ekliyor. `Drop`'un kendi kuralları (hangi tiplerin onu uygulayabildiği, `Clone`/`Copy` ile
ilişkisi) bu kursun konusu değil; ölçülen tek şey bu tetiklenmenin kaynakta **nerede**
gerçekleştiği.

**SK1.** `Defter` ve `Iz`'in kendisi ölçüm aracının tasarım kararıdır, dilin bir zorunluluğu
değil; bir değerin hangi sınıfa girdiğine karar veren şey kodun kendi yapısıdır — bir
kapsamın kapanması, bir taşıma, açık bir çağrı ya da bir kabın içinde olmak. `Iz` tipi bu
dört durumu görünür kılmak için yazıldı, kendisi bunlardan biri değil.

```rust
// omur.rs — bir degerin omru nerede bitiyor: kapsam sonunda mi, tasindigi yerde mi,
// acik cagrida mi, yoksa kabiyla birlikte mi.

use std::cell::RefCell;
use std::rc::Rc;

type Defter = Rc<RefCell<Vec<String>>>;

struct Iz {
    ad: String,
    defter: Defter,
}

impl Iz {
    fn yeni(ad: &str, defter: &Defter) -> Iz {
        Iz {
            ad: ad.to_string(),
            defter: Rc::clone(defter),
        }
    }
}

impl Drop for Iz {
    fn drop(&mut self) {
        self.defter.borrow_mut().push(self.ad.clone());
    }
}

struct Kutu {
    icerik: Iz,
}

fn yut(_alinan: Iz) {
    // Deger buraya tasindi; govde bitince omru burada bitiyor.
}

fn okunan(defter: &Defter) -> Vec<String> {
    defter.borrow().clone()
}

fn yeni_olanlar(defter: &Defter, onceki: usize) -> String {
    let hepsi = okunan(defter);
    hepsi[onceki..].join(", ")
}

fn main() {
    let defter: Defter = Rc::new(RefCell::new(Vec::new()));
    let mut sayim: Vec<(&str, &str)> = Vec::new();

    // --- A: kapsam sonu ---
    let a0 = okunan(&defter).len();
    {
        let _birinci = Iz::yeni("kapsam-1", &defter);
        let _ikinci = Iz::yeni("kapsam-2", &defter);
        let _ucuncu = Iz::yeni("kapsam-3", &defter);
    }
    println!("A kapsam sonu       -> {}", yeni_olanlar(&defter, a0));
    for ad in ["kapsam-1", "kapsam-2", "kapsam-3"] {
        sayim.push((ad, "kapsam sonu"));
    }

    // Golgelenen deger de kapsam sonuna kadar yasar: yeni baglama eskisini bitirmiyor.
    let g0 = okunan(&defter).len();
    {
        let _golge = Iz::yeni("golgelenen", &defter);
        let _golge = Iz::yeni("golgeleyen", &defter);
        println!("   golgeleme aninda -> {}", yeni_olanlar(&defter, g0));
    }
    println!("A golgeleme         -> {}", yeni_olanlar(&defter, g0));
    sayim.push(("golgelenen", "kapsam sonu"));
    sayim.push(("golgeleyen", "kapsam sonu"));

    // --- B: tasindigi yerde ---
    let b0 = okunan(&defter).len();
    {
        let tasinan = Iz::yeni("islev-icine", &defter);
        yut(tasinan);
        println!("   islev doner donmez -> {}", yeni_olanlar(&defter, b0));

        let ic = Iz::yeni("ic-kapsama", &defter);
        {
            let _yeni_sahip = ic;
        }
        println!("   ic kapsam biter bitmez -> {}", yeni_olanlar(&defter, b0));

        let alan = Iz::yeni("yapi-icine", &defter);
        {
            let kutu = Kutu { icerik: alan };
            let _ad_uzunlugu = kutu.icerik.ad.len();
        }
    }
    println!("B tasindigi yerde   -> {}", yeni_olanlar(&defter, b0));
    for ad in ["islev-icine", "ic-kapsama", "yapi-icine"] {
        sayim.push((ad, "tasindigi yerde"));
    }

    // --- C: acik cagrida ---
    let c0 = okunan(&defter).len();
    {
        let erken = Iz::yeni("erken-birakilan", &defter);
        let _gec = Iz::yeni("kapsamda-kalan", &defter);
        drop(erken);
        println!("   acik cagridan sonra -> {}", yeni_olanlar(&defter, c0));
    }
    println!("C acik cagrida      -> {}", yeni_olanlar(&defter, c0));
    sayim.push(("erken-birakilan", "acik cagrida"));
    sayim.push(("kapsamda-kalan", "kapsam sonu"));

    // --- D: kabiyla birlikte ---
    let d0 = okunan(&defter).len();
    {
        let mut liste = Vec::new();
        liste.push(Iz::yeni("kap-1", &defter));
        liste.push(Iz::yeni("kap-2", &defter));
        liste.push(Iz::yeni("kap-3", &defter));
        let _obekte = Box::new(Iz::yeni("obekte", &defter));
        println!("   kap dolu iken -> [{}]", yeni_olanlar(&defter, d0));
    }
    println!("D kabiyla birlikte  -> {}", yeni_olanlar(&defter, d0));
    for ad in ["kap-1", "kap-2", "kap-3", "obekte"] {
        sayim.push((ad, "kabiyla birlikte"));
    }

    // --- rapor ---
    let biten = okunan(&defter);
    println!();
    println!("toplam biten deger: {}", biten.len());

    let siniflar = ["kapsam sonu", "tasindigi yerde", "acik cagrida", "kabiyla birlikte"];
    for sinif in siniflar {
        let adet = sayim.iter().filter(|(_, s)| *s == sinif).count();
        println!("{:<18}{}", sinif, adet);
    }
}
```

```
A kapsam sonu       -> kapsam-3, kapsam-2, kapsam-1
   golgeleme aninda -> 
A golgeleme         -> golgeleyen, golgelenen
   islev doner donmez -> islev-icine
   ic kapsam biter bitmez -> islev-icine, ic-kapsama
B tasindigi yerde   -> islev-icine, ic-kapsama, yapi-icine
   acik cagridan sonra -> erken-birakilan
C acik cagrida      -> erken-birakilan, kapsamda-kalan
   kap dolu iken -> []
D kabiyla birlikte  -> obekte, kap-1, kap-2, kap-3

toplam biten deger: 14
kapsam sonu       6
tasindigi yerde   3
acik cagrida      1
kabiyla birlikte  4
```

## Dört Bölümün Okunuşu

A bölümü üç değer kuruyor (`kapsam-1`, `kapsam-2`, `kapsam-3`) ve iç kapsam kapanır kapanmaz
üçü de deftere düşüyor — çıktıda `kapsam-3, kapsam-2, kapsam-1` sırasıyla. Bu sıralamaya
Sınırlayıcı Ölçüm bölümünde dönülecek. A bölümünün ikinci kısmı gölgelemeyi ölçüyor: aynı
ada iki kez bağlanmak (`golgelenen`, sonra `golgeleyen`) tek bir bitiş üretmiyor, ikisi ayrı
ayrı yaşıyor ve ikisi de kapsam sonunda bitiyor. Gölgeleme anında alınan ölçüm boş çıkıyor
çünkü henüz hiçbir şey bitmedi; gölgeleme yalnız yeni bir bağlama kuruyor, eskisinin ömrünü
kısaltmıyor. Programlama Temelleri kursu (M01/K02) gölgelemeyi kavram olarak kurmuştu ve
Değişkenler ve Değişmezlik dersi (M10/K01) onu tip değiştirebilme yönüyle derinleştirmişti;
buradaki pay dar: gölgeleme bir bitiş değildir.

B bölümü aynı sınıfa düşen üç ayrı taşıma biçimini gösteriyor: bir değerin işleve
geçirilmesi (`islev-icine`), bir iç kapsama yeniden bağlanması (`ic-kapsama`) ve bir yapının
alanına konması (`yapi-icine`). Üçü de dış kapsam kapanmadan önce bitiyor, çünkü sahiplik
her seferinde daha dar bir kapsama taşınıyor ve o dar kapsam önce kapanıyor. `yut` işlevi
ve `Kutu` yapısı bu üç biçimi somutlaştırmak için çekirdeğe eklendi: `yut` bir değeri
parametre olarak alıp hiçbir şey döndürmeden kapsamının sonunda bırakıyor, `Kutu` ise bir
değeri kendi alanına yerleştirip o alanın sahibinin artık `Kutu` örneği olduğunu gösteriyor.
İkisi de dilin bir parçası değil, üç taşıma biçimini yan yana koymak için yazılmış küçük
yardımcılar. Bu üç biçimin ayrıntısına Sahiplik ve Taşıma dersinde girilecek; burada yalnız
üçünün de aynı sınıfa (taşındığı yerde) girdiği görülüyor.

C bölümü tek bir örnekle nadir bir sınıfı gösteriyor: aynı kapsamdaki iki değerden biri
(`erken-birakilan`) bir çağrıyla kapsamı bitmeden bırakılıyor, öbürü (`kapsamda-kalan`)
normal kapsam sonuna kadar bekliyor. On dört değerden yalnız biri bu yolla bitiyor — açık
çağrı, kapsamın kendi akışını beklemeden bir bitişi öne çekiyor.

D bölümü dört değeri tek bir kapta topluyor: bir büyüyen dizi üç eleman tutuyor (`kap-1`,
`kap-2`, `kap-3`) ve öbeğe alınmış tekil bir değer (`obekte`) aynı kapsamda duruyor. Kap
dolu iken defter boş çıkıyor — kap kapanmadan hiçbir eleman bitmiyor. Kap kapandığında dört
değer de aynı anda deftere düşüyor, ama kendi aralarındaki sırayı koruyorlar: `obekte`
listeden önce bitiyor (bildirimin tersi), listenin kendi elemanları ise eklendikleri
sırayla bitiyor.

**SK2.** Büyüyen dizi içindeki elemanların bırakılma sırası (ekleme sırasıyla, indeks
küçükten büyüğe) dilin kendi güvencesidir; bu davranış çekirdeğin seçtiği bir örnek değil,
standart kütüphanenin tanımladığı bir kuraldır.

## Yığıt, Öbek ve Tek Sahip

Bellek düzeninin kendisi bu kursun konusu değil — Bilgisayarlar Nasıl Çalışır kursu
(M01/K01) ve Kaçış Çözümlemesi dersi (M09/K05) yığıt ve öbek ayrımını kavram olarak zaten
kurmuştu, bu üçüncü karşılaşma bir kuram tekrarı değil. Buradaki pay dar ve iki cümleyle
özetlenebilir: ayrım **tipte görünür** ve her değerin **tek bir sahibi** var.

`obekte` değişkeni bunu somutlaştırıyor. Sıradan bir `Iz` değeri (örneğin `kapsam-1`)
doğrudan kendi bağlandığı yerde duruyor; `Box::new(Iz::yeni("obekte", &defter))` ise değeri
öbeğe yerleştiriyor ve bu yerleştirme kodda görünüyor — tipin kendisi `Box<Iz>`, `Iz`
değil. Öbeğe alma konusunun kendisi (özyinelemeli tiplerin nasıl mümkün kıldığı, sahipliğin
nasıl davrandığı) ileride Öbekte Tekil Sahiplik dersinde ele alınacak. Burada görülmesi
gereken tek şey şu: `obekte` de tıpkı yığıttaki üç dizi elemanı gibi aynı deftere, aynı
`Drop` mekanizmasıyla düşüyor. Bir değerin nerede yaşadığı (yığıtta mı öbekte mi) ile ne
zaman bittiği ayrı sorular — biri tipten okunuyor, öbürü kapsamdan.

"Tek sahip" ifadesi burada bir slogan değil, defterin kendisinden okunan bir gözlem.
On dört değerin hiçbiri deftere iki kez düşmüyor — her ad, çıktının tamamında tam olarak bir
kez görünüyor. Bir değerin yığıtta mı öbekte mi durduğu değişse bile bu tekillik değişmiyor:
`obekte` de, `kap-1` de, `kapsam-1` de birer kez bitiyor. Bu gözlem rastgele değil; bir
değerin aynı anda iki ayrı yerde sahiplenilmesi mümkün olsaydı, o değer iki kez bitirilmeye
çalışılır ve defterde aynı ad iki kez görünürdü. Sıradaki ders bu tekilliğin taşıma
sırasında nasıl korunduğunu — sahiplik el değiştirirken eski sahibin neden artık o değere
erişemediğini — doğrudan ölçüyor.

## Sınırlayıcı Ölçüm: Bitiş Sırası Bildirimin Tersidir

A bölümünün üç değeri bunu en açık gösteren örnek. `kapsam-1`, `kapsam-2`, `kapsam-3`
sırasıyla bildiriliyor, ama iç kapsam kapandığında bitiş sırası tam ters:
`kapsam-3, kapsam-2, kapsam-1`. Bu bir ölçüm aracının kendi seçimi değil, dilin kendi
sözü.

**SK3.** Yerel bir kapsamdaki değerler her zaman bildirimin tersi sırayla bitiyor — bu
Rust'ın dil belirtiminin parçası ve gerçekleştirimden gerçekleştirime değişmiyor. Aynı kural
D bölümünde de görülüyor: `obekte`, kendisinden sonra bildirilen `liste`den önce bitiyor.

Bu sıra rastgele değil; kapsamda açılan en son bağlamanın en önce bitmesi, iç içe geçmiş
kaynakların (bir dosyanın açtığı bir bağlantı gibi) her zaman açılış sırasının tersiyle
kapanmasını garanti ediyor. Kaynak koda bakan biri, bir kapsamdaki bitiş sırasını koşum
yapmadan, yalnız bildirim sırasını tersine çevirerek söyleyebiliyor.

Bu güvence yalnız bir sıralama ayrıntısı değil, bir bağımlılık düzeni de kuruyor. Bir
kapsamda ikinci bağlanan bir değer, ilk bağlanan bir değere ait bir kaynağı paylaşıyorsa —
örneğin aynı defteri kendi alanında tutuyorsa — bu ikinci değerin ilk değerden önce bitmesi
gerekiyor; aksi hâlde bitiş sırasında elindeki kaynak zaten kapanmış olurdu. Bildirim
sırasının tersine çevrilmesi tam olarak bunu sağlıyor: en son açılan, elindeki bağımlılıkları
hâlâ canlıyken bitiyor. `omur.rs` çekirdeğinde bu bağımlılık `defter`in kendisi — her `Iz`
değeri kendi `defter` alanını tutuyor ve bu alan, `Iz` değerinin kendisinden sonra değil,
tam olarak onunla birlikte bitiyor.

## Özet

- Bir değerin ömrü dört biçimden birinde bitiyor: kapsam sonu, taşındığı yerde, açık
  çağrıda, kabıyla birlikte; on dört değerin 6'sı kapsam sonunda, 3'ü taşındığı yerde, 1'i
  açık çağrıda, 4'ü kabıyla birlikte bitti.
- Gölgeleme bir bitiş değildir; aynı ada yeniden bağlanmak eski bağlamanın ömrünü
  kısaltmaz.
- Bir değerin yığıtta mı öbekte mi yaşadığı tipten okunur (`Iz` ile `Box<Iz>` farkı);
  nerede yaşadığı, ne zaman bittiğinden ayrı bir sorudur.
- Kapsam sonunda biten değerler her zaman bildirimin tersi sırayla bitiyor; bu dilin
  sözüdür, ölçüm aracının seçimi değil.

## Sonraki Adım

Bu derste bir değerin ömrünün nerede bittiği dört sınıfa ayrıldı ve kapsam sonunun kendi
sırası ölçüldü. Geriye kalan üç sınıftan en yaygını — taşındığı yerde — henüz yalnız üç
örnekle görüldü. Sıradaki ders bu sınıfı derinleştiriyor: sahiplik bir yerden başka bir
yere geçtiğinde bitiş noktasına tam olarak ne oluyor ve üç ayrı taşıma biçimi (işleve, iç
kapsama, yapı alanına) neden hep aynı sonuca varıyor.
