---
title: 'Sahiplik ve Taşıma'
source: 'https://academia.sh/tr/kurslar/sahiplik/sahiplik-ve-tasima'
course: 'Sahiplik ve Bellek Modeli'
language: tr
updated: '2026-09-13T05:09:25+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Bir değerin işleve, iç kapsama ve yapı alanına taşınmasının üçünün de taşındığı yerde sınıfına girdiğini koşturarak gösterir'
    - 'Taşımadan sonra eski bağlamanın neden kullanılamadığını açıklar ve yeni sahibin değeri kullanabildiğini kanıtlar'
    - 'Taşımanın bir kopyalama olmadığını, defterde her değer için tam olarak bir kayıt oluştuğunu ölçerek doğrular'
---

# Sahiplik ve Taşıma

Bir değerin işleve, iç kapsama ve yapı alanına taşınmasının üçü de aynı sınıfa (taşındığı yerde) giriyor ve üçünde de değer tam olarak bir kez bitiyor; taşımadan sonra eski bağlamanın kullanılamaması derleyicinin derleme zamanında sınadığı bir kural, yeni sahip ise değeri sorunsuz kullanabiliyor.

Önceki ders bir değerin kapsam sonunda nasıl bittiğini ölçtü ve taşındığı yerde sınıfına yalnız
üç örnekle değindi. Bu ders o sınıfı derinleştiriyor: sahiplik bir yerden başka bir yere
geçtiğinde bitiş noktasına tam olarak ne oluyor? Eşzamanlılık kursunun (M09/K03) sorduğu "bir
goroutine nasıl duracak" sorusu buna benzer görünse de ayrıdır: orada koşan bir birim durur,
burada bir değer biter.

Programlama Temelleri kursu (M01/K02) bir değerin bir işleve nasıl geçtiğini — değerle
aktarım — kavram olarak kurmuştu; o kursta bu aktarım biçimi Python üzerinden anlatılmış,
işleve geçen bir değerin çağıranın elindeki adı etkilemediği gösterilmişti. Bu derste
ölçülen, Rust'ın aynı sözdizimine (bir değeri bir işleve argüman olarak yazmak) tamamen
farklı bir anlam yüklemesi: bir işleve geçen bir değer, artık işlevin de sahibi olur ve
çağıranın elindeki ad geçerliliğini yitirir. Bu sahiplik değişimi derleme zamanında
sınanıyor, çalışma zamanında değil. Bir değerin bir referans üzerinden, sahiplik vermeden
erişilmesi ayrı bir yol — o yol Ödünç Alma dersinde ele alınacak.

## Üç Taşıma Biçimi

Aynı sınıfa (taşındığı yerde) üç ayrı yoldan girilebiliyor. Bir değer bir **işleve**
argüman olarak geçirilebilir; bir değer aynı kapsamın içinde açılan bir **iç kapsamda**
yeni bir ada yeniden bağlanabilir; bir değer bir **yapının alanına** konabilir. Üçünde de
ortak olan şey, eski bağlamanın artık değeri tutmuyor olması — değer aynı kalıyor, yalnız
ona hangi adın eriştiği değişiyor.

**SK4.** Bir değerin iç kapsamda yeni bir ada bağlanması (`let yeni_sahip = ic;`), önceki
dersteki gölgelemeyle karıştırılmamalı. Gölgeleme aynı ad üzerinde **yeni bir değer**
yaratıyordu ve eskisi kendi kapsam sonuna kadar ayrıca yaşıyordu. Burada tam tersi
oluyor: **aynı değer**, farklı bir ada taşınıyor ve eski ad bir daha o değere erişemiyor.
İkisi de bir "yeniden bağlama" gibi görünse de, biri yeni bir ömür başlatıyor, öbürü var
olan bir ömrün sahibini değiştiriyor.

Üç biçim farklı sözdizimleriyle görünse de aynı tek düzeneğin üç kullanım yeridir: Rust'ta
bir değeri `Copy` işaretli olmayan bir tipte herhangi bir yere yazmak — bir parametreye, bir
değişkene, bir alana — o değeri oradan oraya **taşır**. Söz dizimi hep aynı görünüyor
(`=` işareti, bir çağrı), ama arkasındaki anlam her seferinde aynı: eski konumdaki bit
kalıbı yeni konuma taşınıyor ve eski konum artık geçerli sayılmıyor. Bu derste üç ayrı
yerin (parametre, iç kapsam bağlaması, yapı alanı) hepsinin bu tek düzeneğe indirgendiği
ölçülüyor — üç farklı kural değil, bir kuralın üç görünümü.

Üç biçim pratikte de farklı tasarım kararlarına karşılık geliyor. Bir değeri işleve
taşımak, işlevin o değer üzerinde son söz sahibi olmasını istediğinde tercih ediliyor —
işlev bitince değer de bitiyor, çağıran tarafın onunla bir daha işi olmuyor. Bir değeri iç
kapsamda yeniden bağlamak, aynı değeri farklı bir isimle, genellikle daha dar ve geçici bir
işlem için tutmak istendiğinde görülüyor. Bir değeri bir yapının alanına koymak ise değeri
kalıcı olarak daha büyük bir bütünün parçası yapıyor — bundan sonra değerin ömrü, kendi
kapsamına değil, o yapının ömrüne bağlanıyor. Üçü de aynı düzeneği kullanıyor, ama hangi
birimin (işlev, kapsam, yapı) değerin yeni sınırını çizeceğine göre seçiliyor.

Bu seçim çoğu zaman veri modelinin kendisinden çıkıyor. Bir kayıt işleyen bir program,
kaydı doğrulayan bir işleve taşıyorsa (işleve taşıma), doğrulama bitince kaydın orada
kalmasını bekliyordur — çağıran taraf zaten kaydı bir daha kullanmayacaktır. Aynı program
bir kaydı geçici olarak dönüştürülmüş bir biçimde tutmak istiyorsa (iç kapsama taşıma),
dönüşüm yalnız o dar kapsamda geçerli kalıyor. Bir kayıt kalıcı bir yapının (örneğin bir
listenin ya da bir önbelleğin) parçası olacaksa (yapı alanına taşıma), sahiplik baştan o
yapıya veriliyor. Üç biçim arasında seçim, kod yazarken "bu değer artık kime ait olacak"
sorusuna verilen yanıtla belirleniyor.

## Ölçümün Kesiti

Önceki dersin çekirdeğinden yalnız `Iz`, `Drop` uygulaması ve gözlem defteri kesiti
alınıyor; A, C, D bölümlerine bu derste ihtiyaç yok. Yardımcı kısım ayrı bir dosyaya
konuyor ki üç taşıma biçimi tek bir akışta yan yana görülebilsin.

Yardımcı dosya kendi başına derlenmiyor — `iz.rs` dosyasında bir giriş noktası yok, bu
yüzden çalıştırılamıyor, yalnız çalışma dizinine yazılıyor. `tasima.rs` dosyasının en
başındaki `mod iz;` satırı bu dosyayı asıl derlemenin içine çekiyor; `use iz::{Iz,
yeni_defter, okunan};` ise oradan hangi adların doğrudan kullanılacağını belirtiyor. `Iz`
yapısının `ad` alanı ve `yeni`/`yeni_defter`/`okunan` işlevleri modülün dışından
erişilebilmesi için `pub` işaretli; `defter` alanı ise işaretli değil, çünkü ona yalnız
`Iz`in kendi yöntemleri erişiyor. Görünürlüğün bu şekilde tek tek işaretlenmesi Kurulum ve
Paket Yöneticisi dersinde (M10/K01) zaten kurulmuştu; burada yalnız bir uygulaması var.

```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
// tasima.rs — uc tasima bicimi: isleve, ic kapsama, yapi alanina
mod iz;
use iz::{Iz, yeni_defter, okunan};

struct Kutu {
    icerik: Iz,
}

fn yut(alinan: Iz) {
    println!("islev icinde okunan ad: {}", alinan.ad);
}

fn main() {
    let defter = yeni_defter();

    let tasinan = Iz::yeni("islev-icine", &defter);
    yut(tasinan);
    println!("islev donduktan sonra defter: [{}]", okunan(&defter).join(", "));

    let ic = Iz::yeni("ic-kapsama", &defter);
    {
        let yeni_sahip = ic;
        println!("ic kapsamda okunan ad: {}", yeni_sahip.ad);
    }
    println!("ic kapsam bittikten sonra defter: [{}]", okunan(&defter).join(", "));

    let alan = Iz::yeni("yapi-icine", &defter);
    {
        let kutu = Kutu { icerik: alan };
        println!("yapi alaninda okunan ad: {}", kutu.icerik.ad);
    }
    println!("yapi kapsami bittikten sonra defter: [{}]", okunan(&defter).join(", "));

    let kayitlar = okunan(&defter);
    println!();
    println!("toplam kayit: {}", kayitlar.len());
    for ad in ["islev-icine", "ic-kapsama", "yapi-icine"] {
        let adet = kayitlar.iter().filter(|k| k.as_str() == ad).count();
        println!("{:<14}{} kayit", ad, adet);
    }
}
```

```
islev icinde okunan ad: islev-icine
islev donduktan sonra defter: [islev-icine]
ic kapsamda okunan ad: ic-kapsama
ic kapsam bittikten sonra defter: [islev-icine, ic-kapsama]
yapi alaninda okunan ad: yapi-icine
yapi kapsami bittikten sonra defter: [islev-icine, ic-kapsama, yapi-icine]

toplam kayit: 3
islev-icine   1 kayit
ic-kapsama    1 kayit
yapi-icine    1 kayit
```

Üç satır da aynı düzeni izliyor: değer önce yeni sahibinde **okunuyor** (`alinan.ad`,
`yeni_sahip.ad`, `kutu.icerik.ad`), sonra yeni sahibin kendi kapsamı kapanınca deftere
düşüyor. `yut` işlevinin gövdesi bitince `islev-icine` hemen deftere yazılıyor — işlevin
kendi kapsamı, taşınan değerin yeni ve son kapsamı oluyor. İç kapsamdaki `yeni_sahip` ve
yapı alanındaki `kutu.icerik` için de aynı şey geçerli: ikisi de kendi dar kapsamları
kapanır kapanmaz bitiyor, dış kapsamın kapanmasını beklemiyor.

Erişim biçimi de üç formda farklılaşıyor. İşleve taşınan değere doğrudan parametre adıyla
ulaşılıyor (`alinan`), iç kapsama taşınan değere yeni bağlamanın adıyla (`yeni_sahip`), ama
yapı alanına taşınan değerin artık kendi başına bir adı yok — yalnız `kutu.icerik` yoluyla,
sahibi olan yapı üzerinden erişilebiliyor. Bu üçüncü biçim, taşımanın yalnız "bir değişkeni
başka bir değişkene kopyalamak" olmadığını gösteriyor: değer bir yapının **parçası**
hâline geldiğinde kendi bağımsız adını kaybediyor, artık yalnız kendisini saran yapının
alan yolu üzerinden görünüyor.

## Eski Bağlamanın Kullanılamaması

Kod bu üç taşımadan sonra eski adı (`tasinan`, `ic`, `alan`) bir daha okumuyor — çünkü
okuyamaz. `yut(tasinan)` çağrısından sonra `tasinan.ad`'a erişmeye çalışan bir satır
eklenseydi, derleyici bunu reddederdi: sahiplik `yut`un parametresine geçti ve `tasinan`
artık geçerli bir değere işaret etmiyor. Aynı kural `ic` ve `alan` için de geçerli.

**SK5.** Bu redd bir çalışma zamanı hatası değil, derleme zamanında sınanan bir kuraldır.
Taşınmış bir adı yeniden okumaya çalışan bir kaynak hiç derlenmez; program hiçbir zaman bu
satıra ulaşmaz, bu yüzden yanlış kullanım çalışma zamanında hiçbir maliyete yol açmaz. Bu,
kabul edilen yazımın (yukarıdaki üç blok) neden hiçbir yerde eski adı tekrar okumadığını da
açıklıyor — doğru yazım zaten bu kısıtın içinde kalıyor.

Bu ret, önceki dersteki tek sahip gözlemiyle aynı yerden geliyor: bir değere aynı anda iki
ayrı adın erişebilmesi, o değerin hangi adın kapsamı kapanınca biteceğini belirsizleştirirdi.
Derleyici bunu, taşıma anında eski adı **geçersiz** sayarak önlüyor — eski ad hâlâ kaynakta
duruyor, ama bir daha kullanılamıyor.

Bu kısıtın neyi önlediğini somutlaştırmak için bir zihin deneyi yeterli: `tasinan` taşımadan
sonra da geçerli kalsaydı, hem `tasinan` hem `alinan` aynı `Iz` örneğine erişebilirdi. İkisi
de kendi kapsamı kapanınca bu örneği bitirmeye çalışırdı ve aynı değer iki kez bitirilmiş
olurdu — `defter`e aynı ad iki kez yazılırdı. Derleyici bu durumu hiç doğurmuyor; taşıma
anında yalnız bir adın geçerli kaldığından emin oluyor, geri kalanı (bitişin ne zaman
olacağı) önceki dersin kurallarına bırakıyor.

## Taşıma Zincirlenebilir

Üç biçim tek bir taşımayı gösterdi, ama taşıma art arda da olabilir: bir değer bir işleve
girip oradan başka bir işleve, hatta geri çağırana devredilebilir. Aşağıdaki örnek aynı
`Iz` değerinin iki ayrı işlev sınırını geçip üçüncü bir kapsamda bitmesini ölçüyor.

```rust
// zincir.rs — tasima zincirlenebilir: sahiplik bir islevden digerine devredilebilir
mod iz;
use iz::{Iz, yeni_defter, okunan};

fn ikinci_asama(deger: Iz) -> Iz {
    println!("ikinci asamada okunan ad: {}", deger.ad);
    deger
}

fn ilk_asama(deger: Iz) {
    let devredilen = ikinci_asama(deger);
    println!("ilk asamaya donen ad: {}", devredilen.ad);
}

fn main() {
    let defter = yeni_defter();
    let deger = Iz::yeni("zincirli", &defter);
    ilk_asama(deger);
    println!("zincir bittikten sonra defter: [{}]", okunan(&defter).join(", "));
}
```

```
ikinci asamada okunan ad: zincirli
ilk asamaya donen ad: zincirli
zincir bittikten sonra defter: [zincirli]
```

`deger` burada dört ayrı adın elinden geçiyor: `main`'deki `deger`, `ilk_asama`'nın
parametresi, `ikinci_asama`'nın parametresi ve `ikinci_asama`'nın döndürdüğü değeri
tutan `devredilen`. Her geçiş bir taşıma ve her taşımadan sonra bir önceki ad artık
geçersiz. Zincirin sonunda değer `devredilen`e ait ve `ilk_asama`nın gövdesi bitince orada
bitiyor — `main`de değil. Dört ad, tek bir değer, tek bir bitiş: defterde yalnız
`zincirli` görünüyor, kaç kez taşındığından bağımsız olarak.

Bu, "taşındığı yerde" sınıfının neden bir sayıyla değil bir **konumla** tanımlandığını
gösteriyor. Değerin kaç kez el değiştirdiği önemli değil; ölçülen şey yalnız son sahibin
kapsamı. `ikinci_asama`nın değeri geri döndürmesi de bir taşımadır — dönüş değeri, çağıran
tarafın yeni bir bağlamasına taşınıyor; bu yüzden `devredilen` de kendi payına düşen bir
taşımanın sonucu.

Bir işlevin sahip olduğu bir değeri geri döndürmesi, bu kursta tekrar karşılaşılacak bir
düzen. Bir işlev kendi içinde kurduğu ya da parametre olarak aldığı bir değeri çağırana
geri vermek istediğinde, seçenek bir referans değil bir **sahiplik devri** oluyor — değer
işlevin dönüş tipi olarak yazılıyor ve dönüş, kendi başına bir taşıma sayılıyor. Bu düzen,
Ödünç Denetleyicisi dersinde bir işlevin kendi içinde kurduğu bir değere referans
döndürmesinin neden reddedildiğini anlamak için de gerekiyor: reddedilen tam olarak bu —
referans döndürmek; kabul edilen ise burada görülen — değerin kendisini döndürmek.

## Sınırlayıcı Ölçüm: Taşıma Bir Kopyalama Değildir

Çıktının son üç satırı bunu doğrudan gösteriyor: `islev-icine`, `ic-kapsama` ve
`yapi-icine` adlarının üçü de defterde tam olarak **bir** kez geçiyor. Değer üç ayrı adı
sırayla taşısaydı bile (burada olmuyor, ama farz edelim), her taşıma bir kopya
oluşturmuyor — aynı `Iz` örneği, aynı bellek konumu, yalnız erişim adı değişiyor.

**SK6.** Üç taşıma biçiminin üçü de defterde tam olarak bir kayıt üretti; bu, aynı değerin
iki kez bitirilmeye çalışılmasının kaynak düzeyinde imkânsız olduğunu gösteriyor. Sahiplik
her zaman tek bir adda durduğu için bitiş noktası da her zaman tek bir yerde tetikleniyor —
taşıma bu tekliği bozmuyor, yalnız hangi adın sorumlu olduğunu değiştiriyor.

Taşımanın ömrü **kısaltmadığı** da aynı ölçümden okunuyor. `islev-icine` taşınmadan önce de,
taşındıktan sonra da aynı `Iz` örneği; taşıma bir yeniden oluşturma değil, bir yeniden
adlandırma. Önceki derste görülen dört sınıftan "taşındığı yerde" bu yüzden kendi başına bir
sınıf: değer ne kapsam sonunu bekliyor ne de açık bir çağrı alıyor, yalnız sahibinin kendi
sonunu miras alıyor.

Karşıt durumu düşünmek farkı netleştiriyor. `Iz` değerleri `Clone` uygulasaydı ve üç satır
`yut(tasinan.clone())`, `let yeni_sahip = ic.clone();` biçiminde yazılsaydı, defterde altı
kayıt olurdu: özgün üç değer kendi kapsamlarında, üç kopya da kendi kapsamlarında ayrı ayrı
biterdi. Bu derste `clone` hiç çağrılmadı — taşıma yeni bir `Iz` örneği kurmuyor, var olanı
elden ele geçiriyor. Defterin üç kaydı, altı değil, bu farkın doğrudan kanıtı.

Bu fark yalnız kayıt sayısında değil, işin niteliğinde de görünüyor. Bir kopyalama, kopyanın
kendi verisini ayrıca kurmayı gerektiriyor — `Iz`in durumunda yeni bir `String` ayırmayı;
taşıma ise var olan veriye yeni bir sahip atamaktan ibaret, hiçbir yeni ayırma yapmıyor.
Zincirleme örnekte görülen dört el değiştirme de bu yüzden tek bir `String` üzerinde
gerçekleşti — dört ayrı kopya değil, aynı verinin dört ayrı sahibi.

## Özet

- Bir değer üç yoldan taşınabilir — işleve, iç kapsama, yapı alanına — ve üçü de aynı
  sınıfa (taşındığı yerde) giriyor.
- Taşınan değer yeni sahibinde kullanılabiliyor; eski ad ise taşımadan sonra bir daha
  okunamıyor, çünkü artık geçerli bir değere işaret etmiyor.
- Eski adın kullanılamaz hâle gelmesi derleme zamanında sınanan bir kuraldır; çalışma
  zamanında hiçbir maliyeti yok.
- Taşıma bir kopyalama değildir: defterde her değer için tam olarak bir kayıt oluşuyor,
  aynı değer iki kez bitirilmeye çalışılmıyor.
- Taşıma zincirlenebilir — bir değer birden çok işlev sınırını art arda geçebilir — ama
  kaç kez el değiştirirse değiştirsin, sonunda yalnız bir bitiş noktası oluyor.

## Sonraki Adım

Bu üç taşıma biçiminin ortak noktası, eski adın değeri kaybetmesiydi — sahiplik her
seferinde tam olarak bir yerden bir yere gitti. Sıradaki soru bunun tam tersini
araştırıyor: bir değere, sahipliği hiç vermeden erişmek mümkün mü? Ödünç Alma dersi, bir
değeri ödünç veren adın değeri kaybetmediğini ve ödünç alınan değerin ödünç sırasında
hiçbir yere bitmediğini ölçüyor — taşımanın aksine, burada eski sahip hâlâ sahip kalıyor.
