---
title: 'Yapılarda Referans Tutma'
source: 'https://academia.sh/tr/kurslar/sahiplik/yapilarda-referans-tutma'
course: 'Sahiplik ve Bellek Modeli'
language: tr
updated: '2026-10-21T05:03:44+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Bir yapının alanında referans tutmanın yaşam süresi parametresi gerektirdiğini açıklar'
    - 'Taşınan bir alanla ödünç alınan bir alanın bitiş noktasını koşturarak karşılaştırır'
    - 'Bir yapının referans verdiği veriden uzun yaşayamayacağını redd-kabul çiftiyle gösterir'
---

# Yapılarda Referans Tutma

Bir yapının alanında referans tutmanın yapının kendi ömrüne getirdiği koşul ölçülüyor: yapı, referans verdiği veriden uzun yaşayamaz. Aynı veri bir yapıya taşınarak ve ödünç verilerek tutuluyor; taşınan alanın yapıyla birlikte bittiği, ödünç verilen verinin yapıdan sonra bittiği koşturularak karşılaştırılıyor.

Önceki ders çıkarım kurallarının işlev parametreleri arasında kapsadığı ve kapsamadığı
imzaları ölçtü. Ama açık açıklama yalnızca işlev imzalarında değil, bir yapının kendi
tanımında da gerekebilir: bir yapının alanı bir referans tutuyorsa, yapının kendisi bu
referansın ömrüne bağlı hâle geliyor. Bu ders bu koşulu, aynı veriyi bir yapıya iki farklı
yoldan — taşıyarak ve ödünç vererek — tutan iki kurguyu karşılaştırarak ölçüyor.

Eşzamanlılık kursunun (M09/K03) sorduğu soru burada da farklı: orada koşan bir birimin
durması ölçülüyordu, burada bir yapının içindeki bir alanın bitiş noktası ölçülüyor. Yığıt ve
Öbek dersinde kurulan dört bitiş sınıfı burada yeniden karşımıza çıkıyor, ama bu kez iki
farklı alan türü üzerinden karşılaştırılıyor.

Bu konu boyunca ölçülen şey hep aynı soruydu: bir referansın geçerlilik aralığı
nereden okunuyor. Yaşam Süresi Kavramı dersi bu aralığı bir referans için, Açık Yaşam Süresi
Açıklamaları ve Yaşam Süresi Çıkarım Kuralları dersleri bunu bir işlev imzası için ölçtü. Bu
son ders aynı soruyu bir yapı tanımına taşıyor: bir yapının **kendi** ömrü, taşıdığı bir
referansın ömrüyle nasıl ilişkileniyor.

## İki Yol: Taşımak ve Ödünç Almak

Bir yapı, bir alanına bir değer koymak istediğinde iki seçeneği var: değeri **taşıyabilir**
(alan sahip olur) ya da değere bir **referans tutabilir** (alan yalnızca ödünç alır). Sahiplik
ve Taşıma dersinde görülen taşıma kuralı ilk seçenekte geçerli — alan, kendi başına sahip
olunan sıradan bir değer gibi davranıyor. İkinci seçenek yeni bir soru açıyor: yapının kendisi
ne kadar yaşayabilir, referans verdiği veriden daha uzun yaşayabilir mi?

Cevap hayır ve bu, derleyicinin bir yapı tanımında zorunlu kıldığı bir kural. Bir yapının
alanı bir referans tutuyorsa, yapının kendi tanımı bir yaşam süresi parametresi taşımak
zorunda — bu parametre, yapının kendisinin en fazla ne kadar yaşayabileceğini, referans
verdiği veriyle ilişkilendiriyor.

Bu, önceki iki derste işlev imzaları için kurulan kuralın yapı tanımlarındaki karşılığı.
Orada bir işlevin dönen referansı hangi girdiye bağlı olduğunu söylemek zorundaydı; burada
bir yapının kendisi, taşıdığı referansın hangi kaynağa bağlı olduğunu söylemek zorunda. Fark,
ilişkinin nerede kurulduğu: bir işlev çağrısının ömründe değil, bir yapı örneğinin ömründe.
Bu örnek ne kadar uzun yaşarsa yaşasın — bir değişkende, bir başka yapının alanında, bir
koleksiyonun içinde — taşıdığı referansın kaynağından daha uzun yaşayamayacağı garantisi
değişmiyor.

## Ölçüm: Taşınan Alan Yapıyla Birlikte Bitiyor, Ödünç Alınan Veri Yapıdan Sonra Bitiyor

Aşağıdaki ölçüm iki yapı tanımlıyor: `SahipYapi` bir `Iz` değerine sahip oluyor, `OduncYapi`
bir `Iz` değerine yalnızca referans tutuyor ve bu yüzden `<'a>` parametresi taşıyor. İki yapı
da aynı çekirdek (`Iz`, `Defter`, `Drop`) üzerinde çalışıyor; ölçülen fark yalnızca alanın
taşınıp taşınmadığında.

```rust
// yapida_referans.rs — yapida tasinan alan ile odunc alinan alanin bitis noktasi karsilastirmasi.

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());
    }
}

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

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

struct SahipYapi {
    icerik: Iz,
}

struct OduncYapi<'a> {
    icerik: &'a Iz,
}

fn main() {
    let defter: Defter = Rc::new(RefCell::new(Vec::new()));

    // Tasinan alan: yapi bitince biter.
    let s0 = okunan(&defter).len();
    {
        let tasinan = Iz::yeni("tasinan-alan", &defter);
        let yapi = SahipYapi { icerik: tasinan };
        println!("SahipYapi icindeki alan -> {}", yapi.icerik.ad);
        println!("SahipYapi ayaktayken -> [{}]", yeni_olanlar(&defter, s0));
    }
    println!("SahipYapi bitince    -> {}", yeni_olanlar(&defter, s0));

    // Odunc alinan alan: yapi biter, veri hala yasar.
    let o0 = okunan(&defter).len();
    {
        let odunc_veri = Iz::yeni("odunc-veri", &defter);
        {
            let yapi = OduncYapi { icerik: &odunc_veri };
            println!("OduncYapi icinde     -> {}", yapi.icerik.ad);
        }
        println!("OduncYapi bitince    -> [{}]", yeni_olanlar(&defter, o0));
    }
    println!("odunc-veri bitince   -> {}", yeni_olanlar(&defter, o0));
}
```

```
SahipYapi icindeki alan -> tasinan-alan
SahipYapi ayaktayken -> []
SahipYapi bitince    -> tasinan-alan
OduncYapi icinde     -> odunc-veri
OduncYapi bitince    -> []
odunc-veri bitince   -> odunc-veri
```

`SahipYapi` bölümünde `tasinan` değeri `yapi`'nin alanına **taşınıyor** ve o andan sonra
kendi başına bir bağlaması kalmıyor — yalnızca `yapi.icerik` üzerinden erişilebiliyor. `yapi`
ayaktayken defter boş; `yapi` kapsamı kapanınca `tasinan-alan` deftere düşüyor. Bu, Sahiplik
ve Taşıma dersinde ölçülen "yapı alanına taşınan değer" kalıbının bir tekrarı: alan, yapının
kendisiyle birlikte bitiyor.

`OduncYapi` bölümünde ise `odunc_veri` kendi bağlamasında kalıyor ve `yapi` yalnızca ona bir
referans tutuyor. `yapi`'nin kendi iç kapsamı kapandığında defter **hâlâ boş** — `OduncYapi`
örneğinin bitişi hiçbir kayıt üretmiyor, çünkü `&'a Iz` `Drop` uygulamıyor. `odunc_veri`
kendisi ancak kendi kapsamı (dıştaki blok) kapanınca deftere düşüyor — bu da `OduncYapi`
örneğinin bitişinden **sonra**.

İki bölümün ortak noktası, ikisinde de yalnızca bir kaydın oluşması: `SahipYapi` bölümünde
tek kayıt `tasinan-alan`, `OduncYapi` bölümünde tek kayıt `odunc-veri`. `OduncYapi`'nin
kendisi hiçbir zaman deftere düşmüyor — çünkü yapının kendisi `Drop` uygulamıyor, yalnızca
içindeki referans aracılığıyla başka bir yerdeki `Iz` değerine bakıyor. Bu, referans tutan bir
yapının kendi bitişinin gözlemlenebilir bir yan etkisi olmadığını gösteriyor; gözlemlenebilir
olan yalnızca referans verdiği verinin bitişi ve bu bitiş hiçbir zaman yapının kendi
bitişinden önce gelmiyor — en erken, ikisinin aynı kapsamda birlikte bitmesiyle çakışabiliyor.

**YS9.** Bir yapının alanına taşınan bir değer, yapının kendisiyle birlikte biter. Bir yapının
alanında tutulan bir referansın verisi ise yapıdan **sonra** biter — yapının kendisi hiçbir
zaman kendi verisinden uzun yaşamıyor, ama referans verilen veri yapıdan daha uzun yaşayabilir
ve genellikle de yaşıyor.

## Yapının Kendi Yöntemi Yine Çıkarımla Yazılıyor

`OduncYapi<'a>` bir yaşam süresi parametresi taşısa da, üzerine yazılan yöntemler bu
parametreyi mutlaka tekrarlamak zorunda değil. Önceki ders kurulan çıkarım kuralları burada
da geçerli: `&self` alan bir yöntemin dönen referansı, üçüncü kural gereği `self`'in kendi
ömrüne bağlanıyor ve bu, `'a`'nın ayrıca yazılmasını gereksiz kılıyor. Bu, iki dersin
birbirinden bağımsız olmadığını, aynı kuralların farklı bağlamlarda tekrar tekrar
uygulandığını gösteren somut bir örnek.

```rust
// yontem_cikarimi.rs — omur parametresi tasiyan yapinin kendi yontemi hala cikarimla yaziliyor.

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 OduncYapi<'a> {
    icerik: &'a Iz,
}

impl<'a> OduncYapi<'a> {
    // Aciklamasiz: cikarimin ucuncu kurali (self) burada da gecerli.
    fn ad(&self) -> &str {
        self.icerik.ad.as_str()
    }
}

fn main() {
    let defter: Defter = Rc::new(RefCell::new(Vec::new()));
    let veri = Iz::yeni("paylasilan-veri", &defter);
    let yapi = OduncYapi { icerik: &veri };
    println!("{}", yapi.ad());
}
```

```
paylasilan-veri
```

`impl<'a> OduncYapi<'a>` bloğu `'a`'yı tanıtmak zorunda — yapı tanımı onu gerektiriyor — ama
`fn ad(&self) -> &str` imzası kendi başına hiçbir açıklama taşımıyor. Derleyici burada da
önceki dersteki gibi davranıyor: `&self` tek referans girdisi olduğu için üçüncü kural
uygulanıyor ve dönen `&str`, `self`'in ömrüne bağlanıyor. `self`'in kendisi `OduncYapi<'a>`'ya
bir referans olduğundan, dönen dilim de dolaylı olarak `'a`'nın sınırları içinde kalıyor —
ama bu ilişki `ad` yönteminin kendi imzasında hiç yazılmıyor, çünkü çıkarım onu zaten
karşılıyor.

Bu ayrım, `'a`'nın nerede tanımlandığı ile nerede **kullanıldığı** arasındaki farkı gösteriyor.
`'a`, yapının tanımında ve `impl` bloğunun başlığında görünmek zorunda, çünkü alanın kendisi
ona bağlı. Ama bir yöntemin dönen değeri her zaman `self` üzerinden erişiliyorsa, o yöntemin
kendi imzası `'a`'yı tekrar yazmadan da doğru davranıyor — çıkarım kuralı burada tek bir girdi
(`self`) üzerinden çalışıyor, `'a`'nın kendisiyle hiç ilgilenmiyor. `'a`'nın açıkça yazılması
gereken yer, bir yöntemin dönen referansı `self` **dışında** bir kaynağa (örneğin yönteme ayrı
bir parametre olarak verilen başka bir referansa) bağlandığında ortaya çıkardı; bu, önceki
dersin sınırlayıcı ölçümünün burada da geçerli olduğu anlamına geliyor.

**YS10.** Bir yapı tanımı yaşam süresi parametresi taşıması, o yapı üzerindeki her yöntemin
de açık açıklama taşıması gerektiği anlamına gelmiyor. Çıkarım kuralları yapı yöntemlerinde
de işliyor; parametre yalnızca yapının **tanımında**, alanın kendisi için gerekiyor.

## Sınırlayıcı Ölçüm: Yapı Tanımı Yaşam Süresi Parametresi Olmadan Yazılamaz

`OduncYapi` tanımı `<'a>` parametresi olmadan yazılamıyor. `icerik: &Iz` biçiminde, hiçbir
yaşam süresi belirtmeden yazılan bir alan derleyici tarafından reddediliyor, çünkü yapı
tanımı referansın hangi kaynağa bağlı olduğunu ve yapının o kaynaktan daha uzun
yaşamayacağını hiçbir yerde söylemiyor. Bu, önceki iki derste görülen kalıbın yapı
tanımlarındaki karşılığı: bir referans, ilişkisi kaynağa yazılmadan var olamıyor.

Burada çıkarım kuralları hiç devreye girmiyor — önceki ders görülen üç kural yalnızca işlev
imzalarındaki elenmiş referanslar için tanımlanmıştı, yapı alanları için değil. Bir yapının
alanı, girdi ya da çıktı değil; yapı her çağrıldığında yeniden değerlendirilen bir imza değil,
kendi başına duran bir veri düzeni. Derleyicinin burada varsayabileceği "tek doğru okuma" da
yok: bir alan referans taşıyorsa, o referansın kaynağı yapının **dışında** bir yerde olmak
zorunda ve bu kaynağın kim olduğu yalnızca yazan kişi tarafından bilinebilir bir bilgi.

Kabul edilen yazım yukarıdaki `OduncYapi<'a>` — `<'a>` parametresi yapının kendisine
ekleniyor, alan `&'a Iz` oluyor ve derleyici bu ilişkiyi doğruluyor: `OduncYapi`'nin herhangi
bir örneği, `icerik`'in işaret ettiği veriden daha uzun yaşayamaz. Yukarıdaki ölçüm bu sınırın
içinde kaldı — `yapi` her zaman `odunc_veri`'den önce bitti, hiç sonra değil. `yapi`
örneğinin kendi iç kapsamının dışına taşınmaya çalışıldığını, döndürüldüğünü ya da dış
kapsamdaki bir değişkene atandığını düşünelim: bu derlenmezdi, çünkü örneğin taşıdığı
referans `odunc_veri`'den daha uzun yaşayamaz — kısıt, Ödünç Denetleyicisi dersinde koşturulan
sınırın yapı alanlarındaki biçimi.

**YS11.** Bir yapı, referans taşıyan bir alana sahipse, yaşam süresi parametresi olmadan
tanımlanamaz. Parametre eklenip ilişki yazılınca yapı kullanılabilir hâle geliyor, ama bu
yapının hiçbir örneği kendi referans verdiği veriden uzun yaşayamıyor — parametre bu sınırı
kaldırmıyor, yalnızca kaynağa yazıyor.

## İki Kurgu, Bir Tasarım Kararı

`SahipYapi` ile `OduncYapi` arasındaki seçim bir doğruluk sorunu değil, bir tasarım kararı.
Taşınan alan yapıyı veriden bağımsız kılıyor: `SahipYapi` bir kez kurulduktan sonra, verinin
başka bir yerde yaşayıp yaşamadığını umursamadan taşınabiliyor, döndürülebiliyor, uzun süre
saklanabiliyor. Bunun bedeli bir kopya ya da bir taşıma — veri artık yalnızca o yapıya ait.

Ödünç alınan alan ise veriyi paylaşmayı mümkün kılıyor: aynı `Iz` değeri hem kendi bağlamasında
kullanılabiliyor hem `OduncYapi` üzerinden okunabiliyor, üstelik bir kopya çıkarmadan. Bunun
bedeli de yapının kendi ömrünün veriye bağlanması — `OduncYapi`, verisinden daha uzun
yaşayamadığı için, dönüş değeri olarak kullanılması ya da uzun süre saklanması genellikle daha
kısıtlı. Hangi kurgunun seçileceği, yapının ne kadar süre yaşayacağına ve verinin başka
yerlerde de kullanılıp kullanılmayacağına bağlı.

Bu iki seçenek arasında üçüncü bir yol yok — bir alan ya sahip oluyor ya ödünç alıyor,
ikisinin ortası bulunmuyor. Bir alanın ödünç aldığı veri üzerinde yazma yetkisi de olabilir
(`&'a mut Iz`), ama bu da hâlâ ödünç alma kategorisinde kalıyor: yapı yine veriye sahip
olmuyor, yalnızca üzerinde değiştirme izni taşıyan bir referans tutuyor ve aynı yaşam süresi
koşuluna tabi oluyor. Kursun ilerleyen kısmında görülecek paylaşımlı sahiplik araçları
(öbekte tekil sahiplik, referans sayımı) bu iki seçeneğin ortasında duran üçüncü bir yol gibi
görünebilir, ama aslında değil — onlar da temelde birer sahiplik biçimi, yalnızca sahiplik
kuralının nasıl uygulandığı farklılaşıyor. Referans tutmak, verinin **hiçbir zaman** yapıya
geçmediği tek durum olarak kalıyor.

## Özet

- Bir yapının alanı bir referans tutuyorsa, yapı tanımı bir yaşam süresi parametresi taşımak
  zorundadır; bu parametre olmadan yazılan tanım reddedilir.
- Bir yapının alanına taşınan bir değer, yapının kendisiyle birlikte biter: ömrü
  **taşındığı yerde** bitiyor.
- Bir yapının alanında tutulan bir referansın verisi, yapının kendisinden sonra biter —
  yapı asla verisinden uzun yaşayamaz.
- Yaşam süresi parametresi bu sınırı kaldırmaz, yalnızca kaynağa yazar; parametre eklenince
  bile bir yapı örneği kendi referans verdiği veriden uzun yaşayamaz.
- Taşınan alanla ödünç alınan alan arasındaki seçim bir tasarım kararıdır: biri yapıyı
  veriden bağımsız kılar, öbürü veriyi paylaşmayı mümkün kılar.
- Yaşam süresi parametresi yalnızca yapının tanımında gereklidir; parametreyi taşıyan bir
  yapının yöntemleri, çıkarım kuralları uyduğu sürece kendi başına açıklama taşımayabilir.

## Sonraki Adım

Bu kursun ilk iki konusu boyunca bir değer bir yapıya ya taşındı ya ödünç verildi ve her iki
durumda da o değerin **tek bir sahibi** vardı — taşınan alanın sahibi yapıydı, ödünç verilen
verinin sahibi kendi kapsamıydı; ödünç alınan durumda bile sahiplik hiç bölünmedi, yalnızca
geçici olarak paylaşıldı. Sıradaki konu bu varsayımı kaldırıyor: bir değerin sahibi birden
çok olabilir mi ve bu durumda "bitiş" ne anlama gelir? Öbekte tekil sahiplikle başlayan bu
bölüm, önce özyinelemeli tipleri mümkün kılan tek bir öbek sahipliğini, sonra referans
sayımıyla gerçek anlamda paylaşılan sahipliği ölçüyor.
