---
title: Dilimler
source: 'https://academia.sh/tr/kurslar/sahiplik/dilimler'
course: 'Sahiplik ve Bellek Modeli'
language: tr
updated: '2026-09-13T05:09:25+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Bir dilimin sahiplik almadan bir dizgiyi ya da büyüyen diziyi görüntülediğini ve kaynağın dilim sürerken hiç bitmediğini koşturarak gösterir'
    - 'Dilimin uzunluğunun kaynaktan türediğini ve boş bir dilimin geçerli olduğunu doğrular'
    - 'Dilim yaşarken kaynağın değiştirilemediğini, dilim bittikten sonra değişikliğin sorunsuz geçtiğini kanıtlar'
---

# Dilimler

Bir dilim, sahiplik almadan bir dizginin ya da bir büyüyen dizinin belirli bir aralığını görüntüler: dilim kullanılır, dilim biter, ama kaynak hiç bitmez. Dilimin uzunluğu kaynaktan türer ve boş bir dilim geçerlidir; dilim yaşarken kaynak değiştirilemez, dilim bittikten sonra değişiklik sorunsuz geçer.

Önceki ders bir değerin **tamamına** ödünç verilen referansları ölçtü. Bu ders aynı
sahiplik-vermeden-erişim ilkesini bir değerin yalnız bir **parçasına** uyguluyor: dilim
(slice), bir dizginin ya da bir büyüyen dizinin ardışık bir aralığını, sahiplik almadan
görüntüleyen bir referans türü. Ölçülen yine bir değerin bitişidir, koşan bir birimin durması
değil — Eşzamanlılık kursunun (M09/K03) goroutine sorusu bu kursun ekseninin dışında kalıyor.

Dilim kavramının kendisi Eşzamanlılık kursunda (M09) zaten kurulmuştu — bir dizinin ardışık
bir alt aralığını temsil eden, kendi uzunluğunu taşıyan bir görünüm. Bu derste ölçülen,
Rust'ın dilimi bir aralık söz dizimiyle (`[baslangic..bitis]`) kurması ve önceki üç dersin
kurallarının (sahiplik alınmıyor, kaynak bitmiyor, ödünç ömrü kaynağı aşamıyor) buraya
aynen uygulanması.

Önceki üç ders bir referansın hep **tek bir değere** işaret ettiğini varsaydı: `&Iz`,
`&mut Iz`. Dilim bu varsayımı gevşetiyor — bir referans artık birden çok ardışık değere
birden işaret edebiliyor, ama bunu yaparken sahiplik, kapsam ve paylaşımlı/değiştirilebilir
kurallarının hiçbirini değiştirmiyor. Bu derste ölçülen, kuralların aynı kaldığı, yalnız
neyin ödünç alındığının değiştiği.

## Bir Değerin Bir Parçasını Görüntülemek

Bir dilim, `&T`'nin bir çeşidi: `&[Iz]` bir büyüyen diziden alınan bir görünüm, `&str` bir
dizgiden alınan bir görünüm. İkisi de kaynağın kendi verisine işaret ediyor — veriyi
kopyalamıyor — ve kendi uzunluğunu ayrıca taşıyor. Bir dilim aldığında kaynağın sahibi
değişmiyor, yalnız o aralığa geçici bir erişim kuruluyor.

Aralık söz dizimi `[baslangic..bitis]` biçiminde: `baslangic` dahil, `bitis` hariç. En
basit hâliyle, sahiplenme sorusu hiç devreye girmeden, aralığın kendisi şöyle okunuyor.

```rust
// temel_dilim.rs — dilim sozdizimi: baslangic..bitis araligi
fn main() {
    let sayilar = [10, 20, 30, 40, 50];
    let orta = &sayilar[1..4];
    println!("kaynak: {:?}", sayilar);
    println!("dilim: {:?}", orta);
    println!("dilim uzunlugu: {}", orta.len());
}
```

```
kaynak: [10, 20, 30, 40, 50]
dilim: [20, 30, 40]
dilim uzunlugu: 3
```

`&sayilar[1..4]` indeks 1'den başlayıp indeks 4'e (dahil değil) kadar olan üç elemanı
görüntülüyor — `20`, `30`, `40`. `sayilar`'ın kendisi burada `i32` gibi kopyalanabilir bir
tip taşıdığı için sahiplik sorusu görünmüyor; asıl soru, kaynağın kendisi kopyalanamayan,
`Drop` uygulayan bir tip taşıdığında ortaya çıkıyor — tam da bu dersin geri kalanının
ölçtüğü durum. `[1..4]` yazımının kendisi `sayilar`ın türünü değiştirmiyor; `sayilar` hâlâ
sabit uzunluklu bir dizi, `orta` ise ayrı bir tip — belirli bir uzunluğu olmayan, kaynaktan
türeyen bir dilim.

## Ölçüm: Kaynak Hiç Bitmez

Aşağıdaki ölçüm üç `Iz` değeri tutan bir büyüyen diziden ilk iki elemanı görüntüleyen bir
dilim alıyor, dilimi kullanıyor, dilimin kapsamını kapatıyor ve ardından kaynağı
değiştiriyor.

```rust
// iz.rs — bir degerin bitisini kaydeden olcum yardimcisi
use std::cell::RefCell;
use std::rc::Rc;

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

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

impl Iz {
    pub 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());
    }
}

pub fn yeni_defter() -> Defter {
    Rc::new(RefCell::new(Vec::new()))
}

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

```rust
// dilim_omru.rs — dilim sahiplik almadan gorunturur, kaynagi bitirmez ama kilitler
mod iz;
use iz::{Iz, yeni_defter, okunan};

fn main() {
    let defter = yeni_defter();
    let mut liste = vec![
        Iz::yeni("bir", &defter),
        Iz::yeni("iki", &defter),
        Iz::yeni("uc", &defter),
    ];
    let once = okunan(&defter).len();

    {
        let goruntu = &liste[0..2];
        println!("dilim uzunlugu: {}, ilk ad: {}", goruntu.len(), goruntu[0].ad);
        println!("dilim yasarken defter: [{}]", okunan(&defter)[once..].join(", "));
    }
    println!("dilim bittikten sonra defter: [{}]", okunan(&defter)[once..].join(", "));

    liste.push(Iz::yeni("dort", &defter));
    println!("dilim bittigi icin liste degistirildi, uzunluk: {}", liste.len());
}
```

```
dilim uzunlugu: 2, ilk ad: bir
dilim yasarken defter: []
dilim bittikten sonra defter: []
dilim bittigi icin liste degistirildi, uzunluk: 4
```

`goruntu` yalnız `liste`nin ilk iki elemanını görüntülüyor, ama üç elemanın da sahibi hâlâ
`liste`. Dilim yaşarken de, dilimin kapsamı kapandıktan sonra da defter boş — `bir`, `iki`
ve `uc` değerlerinin hiçbiri bitmiyor, çünkü dilim onlara sahip olmadı, yalnız onlara
baktı. `liste`nin kendisi bu ölçümde hiç bitmiyor (kod dosyanın sonunda kapanmadığı için);
görülen tek bitiş, dilimin kendi kapsamının kapanması — ki bu da deftere hiçbir şey
yazmıyor, çünkü `&[Iz]` tipinde bir dilim `Drop` uygulamıyor.

Burada dikkat edilmesi gereken bir ayrıntı var: `goruntu` yalnız ilk iki elemanı (`bir`,
`iki`) görüntülüyor, üçüncü eleman (`uc`) dilimin dışında kalıyor. Buna rağmen ölçüm
`liste`nin tamamının hâlâ sahibinde durduğunu gösteriyor — dilimin kapsamadığı `uc` da,
kapsadığı `bir` ve `iki` de aynı şekilde etkilenmiyor. Dilim, kaynağın yalnız bir alt
kümesini **okumak** için bir pencere açıyor; kaynağın geri kalanının sahipliğine ya da
ömrüne hiçbir şekilde karışmıyor.

`goruntu[0].ad` erişimi de bunu somutlaştırıyor: `goruntu[0]` dilimin ilk elemanına
işaret eden bir `&Iz` üretiyor (sahiplik değil, yeni bir ödünç) ve `.ad` bu ödünç
üzerinden okunuyor. Aynı satırda üç ayrı ödünç iç içe geçmiş durumda — `liste`den
`goruntu`ya, `goruntu`dan `goruntu[0]`'a, `goruntu[0]`'dan `.ad`'a — ama hiçbiri
sahiplik istemiyor, hepsi aynı temel `Iz` değerlerine kadar geri gidiyor.

**SK10.** Bir dilim, aynı `&T` referansı gibi, işaret ettiği elemanların sahibi değil.
Kapsamı kapandığında yalnız kendisi (dilimin kendi `başlangıç, uzunluk` çifti) yok olur;
elemanların hiçbiri bundan etkilenmez. Önceki dersteki "referans kaynağı bitirmez" kuralı
burada aynen geçerli, yalnız görünürlük tek bir değer yerine ardışık bir aralık.

## Sınırlayıcı Ölçüm: Dilim Kaynağı Kilitler

`liste.push(...)` satırı `goruntu`nun kapsamı kapandıktan **sonra** çalışıyor. Bu sıralama
zorunlu: `goruntu` hâlâ kapsamdayken aynı satır eklenseydi, derleyici reddederdi. `goruntu`
`liste`nin paylaşımlı bir ödüncü ve `push` çağrısı `liste`yi değiştirmek için
değiştirilebilir bir ödünç istiyor — Ödünç Alma dersinde kurulan "aynı anda bir yazan ya da
çok okuyan" kuralı burada da geçerli, yalnız ödünç aldığı şey artık bütün değer değil,
onun bir parçası.

**SK11.** Bir dilim kaynağının **tamamını** kilitliyor, yalnız görüntülediği aralığı değil.
`goruntu` yalnız ilk iki elemanı görüntülese de, `liste`nin herhangi bir yerine (örneğin
sona) eleman eklemeyi de engelliyor — çünkü bir ekleme büyüyen dizinin kendi iç düzenini
yeniden ayarlayabilir ve dilimin işaret ettiği konumları geçersiz kılabilir. Kısıt dilimin
kapsadığı elemanlarla sınırlı değil, kaynağın bütününe yayılıyor.

Bu, "dilim kaynağın yalnız bir parçasını görüntüler" cümlesiyle ilk bakışta çelişiyor
gibi görünebilir — görüntülenen parça küçük, ama kilitlenen yüzey büyük. Çelişki yok:
dilim yalnız kendi aralığındaki elemanları **okumaya** izin veriyor, ama kaynağın kendi
düzeninde (kaç eleman tuttuğu, elemanların nerede durduğu) herhangi bir değişiklik,
dilimin dayandığı varsayımı bozabileceği için, o değişiklik dilim yaşarken hiç
başlatılamıyor. Görüntülenen kısım dar, korunan varsayım geniş.

Kabul edilen yazım bu sırayı zaten koruyor: dilim önce kendi dar kapsamında kullanılıp
bırakılıyor, `push` ancak ondan sonra, `liste`ye tek başına erişimin olduğu bir noktada
çağrılıyor. Aynı işi ters sırayla yazmaya çalışmak — önce değiştirip sonra eski dilimi
okumaya devam etmek — derleyici tarafından hiç derlenmez.

Bu kısıtın neyi önlediği somut: `push` bir büyüyen dizinin arka planındaki depolama
alanını gerektiğinde yeniden ayırabilir — dizi büyürken bütün elemanlar yeni bir konuma
taşınabilir. `goruntu` eski konumlara işaret ediyor olsaydı ve `push` bu taşımayı
tetikleseydi, `goruntu` artık geçerli olmayan bir bellek bölgesine işaret ediyor olurdu.
Derleyici bu senaryoyu, dilim yaşarken kaynağı değiştiren hiçbir çağrıya izin vermeyerek
baştan kapatıyor — `push`un gerçekten yeniden ayırma yapıp yapmayacağını bilmesi bile
gerekmiyor, kural bütün değiştirici çağrılar için aynı.

Aynı kısıt tek bir eleman okumak için de geçerli: `liste[2]` gibi bir doğrudan indeksleme
`goruntu` kapsamdayken sorun çıkarmaz, çünkü o da yalnız okuyor — paylaşımlı iki ödünç bir
arada durabiliyor. Sorun yalnız bir **değişiklik** aynı anda talep edildiğinde başlıyor.

## Dilim, Bir İşleve Kaynağı Taşımadan Geçirilir

Ödünç Alma dersindeki `oku` işlevi tek bir değeri, sahiplik istemeden alıyordu. Aynı
düzenek bir dilim için de geçerli: bir işlev parametresini `&[Iz]` olarak yazarsa, hem
kaynağın tamamını hem de yalnız bir aralığını, sahiplik istemeden kabul edebiliyor.

```rust
// dilim_parametre.rs — bir islev dilim alarak kaynagi tasimadan isler
mod iz;
use iz::{Iz, okunan, yeni_defter};

fn adlari_birlestir(dilim: &[Iz]) -> String {
    let mut sonuc = String::new();
    for (i, iz) in dilim.iter().enumerate() {
        if i > 0 {
            sonuc.push('+');
        }
        sonuc.push_str(&iz.ad);
    }
    sonuc
}

fn main() {
    let defter = yeni_defter();
    let liste = vec![
        Iz::yeni("a", &defter),
        Iz::yeni("b", &defter),
        Iz::yeni("c", &defter),
    ];

    println!("tum liste: {}", adlari_birlestir(&liste));
    println!("ilk iki: {}", adlari_birlestir(&liste[..2]));
    println!("cagrilardan sonra defter: [{}]", okunan(&defter).join(", "));
}
```

```
tum liste: a+b+c
ilk iki: a+b
cagrilardan sonra defter: []
```

`adlari_birlestir` işlevi hem `&liste` (tüm kaynak) hem `&liste[..2]` (bir alt aralık) ile
çağrılabiliyor — parametre tipi `&[Iz]` olduğu için ikisi de aynı işleve uyuyor. `&liste`
burada bir dilime **dönüştürülüyor**: büyüyen dizinin tamamına bir referans, otomatik
olarak baştan sona bir dilime karşılık geliyor. İki çağrıdan sonra da defter boş —
`adlari_birlestir` hiçbir zaman `liste`nin elemanlarına sahip olmadı, yalnız onları okudu.
Bu, bir işlevin sahiplik istemeden **hem bütünü hem parçayı** aynı imzayla kabul
edebilmesinin somut örneği.

## Değiştirilebilir Dilim, Kapsadığı Elemanları Değiştirir

Buraya kadar görülen dilimler hep paylaşımlıydı (`&[Iz]`). Bir dilim de `&mut [Iz]`
olarak alınabilir ve bu durumda kapsadığı elemanlar üzerinde yazma izni de taşır —
Ödünç Alma dersindeki paylaşımlı/değiştirilebilir ayrımı burada da aynen geçerli.

```rust
// dilim_degistirilebilir.rs — degistirilebilir bir dilim, kapsadigi elemanlari degistirebilir
mod iz;
use iz::{Iz, yeni_defter, okunan};

fn main() {
    let defter = yeni_defter();
    let mut liste = vec![
        Iz::yeni("x", &defter),
        Iz::yeni("y", &defter),
        Iz::yeni("z", &defter),
    ];

    {
        let goruntu = &mut liste[0..2];
        for iz in goruntu.iter_mut() {
            iz.ad.push_str("-yeni");
        }
    }
    println!("degisiklikten sonra adlar: {}, {}, {}", liste[0].ad, liste[1].ad, liste[2].ad);
    println!("hicbir sey bitmedi, defter: [{}]", okunan(&defter).join(", "));
}
```

```
degisiklikten sonra adlar: x-yeni, y-yeni, z
hicbir sey bitmedi, defter: []
```

`goruntu` burada `liste`nin ilk iki elemanını değiştirilebilir olarak görüntülüyor;
döngü içindeki `iz.ad.push_str(...)` bu iki elemanın `ad` alanını gerçekten değiştiriyor.
Üçüncü eleman (`z`) dilimin dışında kaldığı için değişmiyor — çıktı bunu doğruluyor.
Kapsam kapandığında hiçbir değer bitmiyor, çünkü değiştirilebilir bir dilim de, tıpkı
paylaşımlı bir dilim gibi, sahiplik almıyor; yalnız o aralığa yazma izni taşıyor.

Bu örnekte de aynı anda yalnız bir değiştirilebilir dilim var; `goruntu` kapsamdayken
`liste`ye başka hiçbir erişim (ne paylaşımlı ne değiştirilebilir) açılamazdı. `goruntu`nun
kapsamı kapandıktan sonra `liste[0].ad` gibi doğrudan indekslemeler serbestçe kullanılabiliyor
— tıpkı Sınırlayıcı Ölçüm bölümünde görülen `push` örneğinde olduğu gibi, kısıt yalnız
dilimin kendi kapsamı boyunca geçerli.

## Uzunluk Kaynaktan Türer, Boş Dilim Geçerlidir

Dilimin uzunluğu kendi başına bir bilgi taşımıyor, kaynaktan hesaplanıyor. Bir dizgi
üzerinde de aynı aralık söz dizimi geçerli.

```rust
// dizgi_dilimi.rs — dilimin uzunlugu kaynaktan turer, bos dilim de gecerlidir
fn main() {
    let metin = String::from("olcum");
    let tam = &metin[..];
    let bos = &metin[0..0];
    println!("kaynak uzunluk: {}", metin.len());
    println!("tam dilim uzunluk: {}", tam.len());
    println!("bos dilim uzunluk: {}", bos.len());
    println!("bos dilim gecerli mi: {}", bos.is_empty());
}
```

```
kaynak uzunluk: 5
tam dilim uzunluk: 5
bos dilim uzunluk: 0
bos dilim gecerli mi: true
```

`&metin[..]` bütün aralığı, `&metin[0..0]` ise hiçbir karakter kapsamayan boş bir aralığı
görüntülüyor. `tam.len()` kaynağınkiyle aynı çıkıyor çünkü aralık baştan sona; `bos.len()`
sıfır, ama `bos` geçersiz bir değer değil — kendi başına geçerli bir dilim, yalnız hiçbir
şey kapsamıyor. `is_empty()` çağrısı bunu doğruluyor: boş bir dilim üzerinde çağrılan
sıradan bir yöntem, hiçbir özel durumla karşılaşmadan çalışıyor.

`metin.len()`in burada verdiği sayı dizginin bayt uzunluğu — bu, dizginin kendisinin bir
bayt dizisi olduğu ve karakter sayısından ayrıştığı Koleksiyonlar dersinde (M10/K01) zaten
ele alınmıştı. Bu dersin payı ayrı: aralığın kendisi nasıl kuruluyor ve ne zaman geçerli
sayılıyor. `metin`in içeriği yalnız ASCII karakterler taşıdığı için burada bayt uzunluğu
ile karakter sayısı çakışıyor; aradaki farkın kendisi bu dersin konusu değil.

**SK12.** Bir dilimin `başlangıç == bitiş` olması bir hata durumu değil, sıfır uzunluklu
geçerli bir dilim üretiyor. Bu, bir işlevin örneğin "eşleşen kısım" olarak boş bir aralık
döndürebilmesini, çağıranın bunu ayrı bir özel durum olarak ele almak zorunda kalmadan
işleyebilmesini sağlıyor. Boş bir dilim üzerinde `len()`, `is_empty()`, hatta bir döngüyle
gezinme (sıfır kez dönerek) sorunsuz çalışıyor — kaynağın kendisi boş olmasa bile.

Dört ders boyunca ödünç almanın taşıdığı üç soru burada da aynı yanıtları veriyor: kaynak
bitiyor mu (hayır), ömür uzuyor mu (hayır, dilimin kapsamı kaynağınkini hiçbir zaman
aşamıyor) ve paylaşımlı/değiştirilebilir ayrımı geçerli mi (evet — bir `&mut [Iz]` dilimi
de alınabilirdi, o zaman kısıtlar Ödünç Alma dersindeki değiştirilebilir referansla
birebir aynı olurdu). Dilim, bu üç soruya yeni bir yanıt getirmiyor; sahip olduğu tek yeni
şey, görüntülediği aralığın **boyutu** — tek bir değer yerine ardışık bir küme.

## Özet

- Bir dilim (`&[T]`, `&str`), kaynağın ardışık bir aralığını sahiplik almadan görüntüler;
  kaynağın kendisi dilim yüzünden hiçbir zaman bitmiyor — kaynağın ömrü kendi **kapsam
  sonunda** bitiyor.
- Dilim yalnız işaret ettiği aralığı değil, kaynağın **bütününü** kilitliyor — dilim
  yaşarken kaynak değiştirilemiyor, dilim bittikten sonra değişiklik sorunsuz geçiyor.
- Dilimin uzunluğu kaynaktan türüyor; bir dilim kendi başına bağımsız bir uzunluk bilgisi
  taşımıyor.
- `başlangıç == bitiş` olan bir dilim geçerlidir ve sıfır uzunluk taşır; boş bir dilim özel
  bir durum değildir.
- Dilim de bir referans olduğu için önceki iki dersin bütün kuralları (paylaşımlı/
  değiştirilebilir ayrımı, kapsamın kaynağı aşamaması) burada da geçerli.
- Bir işlev parametresini `&[T]` ya da `&mut [T]` yazmak, o işlevin hem kaynağın
  tamamını hem yalnız bir aralığını, sahiplik almadan aynı imzayla kabul etmesini sağlar.

## Sonraki Adım

Bu dört ders boyunca ödünç almanın kuralları tek tek ölçüldü — bütün değer, bir parça,
paylaşımlı ya da değiştirilebilir; her seferinde kaynak bitmedi, ömür kaynağı aşmadı ve
aynı anda bir yazan ya da çok okuyan kısıtı korundu. Bu kurallar dört ayrı ders boyunca hiç
çelişmeden aynı kaldı, yalnız uygulandıkları yüzey değişti. Sıradaki ders bu kuralları
uygulayan mekanizmanın kendisine dönüyor: ödünç denetleyicisi, derleme zamanında tam olarak
neyi sınıyor ve bu denetim aynı işi yapan farklı yazımlar arasında nasıl bir seçim
bırakıyor?
