---
title: 'Tip Çıkarımı'
source: 'https://academia.sh/tr/kurslar/cpp-standart-kutuphane/tip-cikarimi'
course: 'Kaynak Yönetimi ve Standart Kütüphane'
language: tr
updated: '2026-09-26T03:02:47+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - "auto'nun bir ifadenin const'unu ve referansını nasıl düşürdüğünü açıklar."
    - 'auto&, const auto& ve auto&& arasındaki farkı kaynağa etkisiyle birlikte ayırt eder.'
    - "decltype ile decltype(auto)'nun tip çıkarımını farklı kurallarla yaptığını gösterir."
    - 'Yapısal bağlamada kopya ile referansın kaynağa farklı sonuç bıraktığını doğrular.'
---

# Tip Çıkarımı

auto'nun const ve referansı düşürmesi, auto&/const auto&/auto&&, decltype ve decltype(auto), yapısal bağlamada kopya-referans farkı ve tip çıkarımının kaynağa ne bıraktığı.

Önceki ders bir görünümün lvalue'dan kurulunca kapsayıcıyı **aynen** bıraktığını, rvalue'dan
kurulunca taşıyan yapıcının kapsayıcıyı **boş**a çevirdiğini gösterdi. Her iki örnekte de
`auto` bir yerde duruyordu — görünümün gerçek tipini yazmak yerine derleyiciye bıraktık. Bu
ders o kısayolun ne yaptığını açıyor: `auto` bir ifadenin tipini nasıl çıkarır, hangi durumda
`const`'u ve referansı düşürür, hangi yazımla düşürmez. Kursun ölçtüğü soru burada da aynı:
bir tip çıkarımı, kaynağa ne bırakır?

## auto Neyi Atar, Neyi Düşürür

`auto` bir başlatıcı ifadesinden tip çıkarır; ama çıkardığı tip, ifadenin tipiyle birebir
aynı değildir. Kural şu: `auto` kendi başına yazıldığında ifadenin **const'unu ve
referansını düşürür**, geriye yalnız temel tip kalır. Aşağıdaki örnek bunu gösteriyor.

```cpp
// auto-dusurme.cpp — auto const ve referansi nasil dusuruyor
#include <cstdio>

int main() {
    const int sabit = 42;
    int deger = 10;
    int& referans = deger;

    auto a = sabit;      // int -- const dustu
    auto b = referans;   // int -- referans dustu

    a = 99;
    b = 99;

    std::printf("sabit %d, deger %d\n", sabit, deger);
    std::printf("a %d, b %d\n", a, b);
    return 0;
}
```

```text
sabit 42, deger 10
a 99, b 99
```

`a` ve `b`, `sabit` ile `referans`ın birer kopyasıdır; ikisine de yazmak kaynağı etkilemez.
`sabit` 42'de, `deger` 10'da kalıyor. **KT39.** `auto`, bir ifadenin const'unu ve
referansını düşürerek bağımsız bir kopya üretir; kopyaya yazmak kaynağa hiçbir şey
bırakmaz — kaynak **aynen** kalır, çünkü kopyanın kendisi ayrı bir nesnedir.

## auto& ile Referansa Bağlanmak

`auto&` yazıldığında referans düşmez; çıkarılan tip başlatıcının kendisine bağlanan bir
referanstır. Bu, `auto`'nun tam tersi bir davranış: kopya değil, kaynağın kendisi.

```cpp
// auto-referans.cpp — auto& bir kopyaya degil kaynagin kendisine baglanir
#include <cstdio>

int main() {
    int deger = 10;
    int& referans = deger;

    auto& baglanti = referans;   // int& -- referans dusmuyor
    baglanti = 99;

    std::printf("deger %d\n", deger);
    return 0;
}
```

```text
deger 99
```

`baglanti` üzerinden yapılan atama `deger`e ulaşıyor; `auto&`, `referans`ın referans
olduğunu unutmadı. `auto` ile `auto&` arasındaki tek fark bir `&` işareti, ama sonuç
tersine dönüyor: biri kopya kurar, öteki kaynağın kendisine bağlanır.

## const auto&: Kopyasız Salt Okuma

Bir kapsayıcıyı yalnız okumak için gezerken `auto` her elemanı kopyalar. Eleman büyükse
(bir `std::string`, bir kayıt) bu kopyalama gereksiz bir maliyettir. `const auto&`, kopya
almadan kaynağın kendisini salt okunur biçimde bağlar.

```cpp
// const-auto-referans.cpp — buyuk elemani kopyalamadan okumak
#include <cstdio>
#include <string>
#include <vector>

int main() {
    std::vector<std::string> stok{"elma", "armut", "kiraz"};

    for (const auto& ad : stok) {
        std::printf("%s\n", ad.c_str());
    }

    std::printf("eleman sayisi %zu\n", stok.size());
    return 0;
}
```

```text
elma
armut
kiraz
eleman sayisi 3
```

Döngü boyunca hiçbir `std::string` kopyalanmadı; `ad` her adımda `stok`un o anki
elemanına bağlandı. `const` derleyiciye bu bağlantı üzerinden yazma yapılmayacağını
söylüyor, `stok` döngü sonunda **aynen** kalıyor. Kopya almamak burada bir performans
kararı, kaynağa etkisi değişmiyor: `const auto&` de, kopyalayan `auto` da salt okuma
sırasında kaynağı bozmaz — fark, ara kopyanın var olup olmamasında.

## auto&&: İletme Referansı

`auto&&` yazıldığında çıkarılan tip başlatıcının değer kategorisine göre değişir: bir sol
değerle başlatılırsa sıradan bir referansa (`T&`), bir sağ değerle başlatılırsa bir sağ
değer referansına (`T&&`) döner. Bu ikili davranışı gösteren `auto&&` biçimine **iletme
referansı** denir.

```cpp
// auto-iletme-referansi.cpp — auto&& deger kategorisine gore farkli tip cikarir
#include <cstdio>
#include <string>

int main() {
    std::string ad = "elma";

    auto&& sol_deger_baglantisi = ad;                    // string&
    auto&& sag_deger_baglantisi = std::string("armut");  // string&&

    sol_deger_baglantisi += " (guncellendi)";

    std::printf("ad: %s\n", ad.c_str());
    std::printf("sag deger: %s\n", sag_deger_baglantisi.c_str());
    return 0;
}
```

```text
ad: elma (guncellendi)
sag deger: armut
```

`sol_deger_baglantisi`, `ad`ın kendisine bağlandığı için üzerine yapılan ekleme `ad`e
ulaşıyor. `sag_deger_baglantisi` ise geçici bir nesneye bağlandı ve onun ömrünü ifadenin
sonuna kadar uzattı. İletme referansı yalnız `auto&&` ya da bir şablon parametresi
`T&&` biçiminde çıkarımla ortaya çıkar; elle yazılmış `std::string&&` bu davranışı
göstermez, çünkü tipi zaten sabittir, çıkarılmaz.

## decltype ve decltype(auto)

`decltype`, `auto`dan farklı bir kurala uyar: bir ifadenin tipini, kaynağını
değiştirmeden **olduğu gibi** verir. `auto` referansı düşürürken `decltype` düşürmez.

```cpp
// decltype-ornek.cpp — decltype referansi dusurmez
#include <cstdio>

int main() {
    int deger = 10;
    int& referans = deger;

    decltype(deger) a = 1;        // int
    decltype(referans) b = deger; // int& -- referans dusmuyor

    b = 42;

    std::printf("deger %d, a %d\n", deger, a);
    return 0;
}
```

```text
deger 42, a 1
```

`b`, `decltype(referans)` sayesinde `int&` tipini aldı ve `deger`in kendisine bağlandı;
`a` ise sıradan bir `int` kopyası. `auto` burada ikisini de `int`e indirgerdi.

`decltype(auto)`, bir işlevin dönüş tipini `decltype` kurallarıyla çıkarmak için
kullanılır — ama bir tuzak taşır: dönüş ifadesinin **parantez içine alınması**, çıkarılan
tipi değiştirir. Aşağıdaki iki işlev aynı değişkeni döndürüyor gibi görünür, ama biri
değer, öteki referans çıkarır.

```cpp
// decltype-auto-parantez.cpp — parantez ifadeyi sol degere cevirip tipi degistirir
#include <cstdio>
#include <type_traits>

int sayac = 0;

decltype(auto) artir_ve_don() {
    ++sayac;
    return sayac;     // decltype(auto) -> int (degisken adi tek basina)
}

decltype(auto) artir_ve_don_parantezli() {
    ++sayac;
    return (sayac);   // decltype(auto) -> int& (parantezli ifade bir sol deger)
}

int main() {
    constexpr bool ilki_deger = std::is_same_v<decltype(artir_ve_don()), int>;
    constexpr bool ikincisi_referans =
        std::is_same_v<decltype(artir_ve_don_parantezli()), int&>;

    std::printf("ilki deger mi: %s\n", ilki_deger ? "evet" : "hayir");
    std::printf("ikincisi referans mi: %s\n", ikincisi_referans ? "evet" : "hayir");
    return 0;
}
```

```text
ilki deger mi: evet
ikincisi referans mi: evet
```

`decltype(auto)`, `return sayac;` için tek başına bir değişken adı görüp `int` çıkarır.
`return (sayac);` için ise parantezli ifadeyi bir sol değer olarak okur ve `int&` çıkarır.
İki işlev de burada `sayac`'ın kendisi genel kapsamda tanımlı olduğu için güvenle
çalışıyor; ama işlev içinde tanımlı **yerel** bir değişkeni aynı şekilde parantezle
döndürmek, işlev bittiğinde yok olan bir nesneye referans üretir — çağıran taraf bu
referansı okumadan önce bile tanımsız davranışa girilmiş olur. Bu yüzden `decltype(auto)`
dönüşünde parantez, göz ardı edilebilecek bir yazım tercihi değildir.

## Yapısal Bağlama: Kopya mı, Referans mı

Yapısal bağlama bir kayıt tipini (bir `std::pair`, bir `std::map`'in elemanı) tek satırda
adlandırılmış parçalara ayırır: `auto [ad, adet] : stok`. Buradaki `auto` da aynı kuralı
izler — kaynağı kopyalar, referans istiyorsan `&` eklemen gerekir. Sırasız bir kapsayıcının
gezinme sırası tanımsız olduğundan aşağıdaki örnek `std::map` kullanıyor; anahtara göre
sıralı olduğu için çıktısı kararlıdır.

```cpp
// yapisal-baglama.cpp — kopya ile referansli yapisal baglamanin farki
#include <cstdio>
#include <map>
#include <string>

int main() {
    std::map<std::string, int> stok{{"elma", 4}, {"armut", 2}};

    for (auto [ad, adet] : stok) {
        adet += 100;   // yalnizca kopyayi degistiriyor
    }

    std::printf("kopyadan sonra:");
    for (const auto& [ad, adet] : stok) {
        std::printf(" %s=%d", ad.c_str(), adet);
    }
    std::printf("\n");

    for (auto& [ad, adet] : stok) {
        adet += 100;   // kaynagin kendisini degistiriyor
    }

    std::printf("referanstan sonra:");
    for (const auto& [ad, adet] : stok) {
        std::printf(" %s=%d", ad.c_str(), adet);
    }
    std::printf("\n");
    return 0;
}
```

```text
kopyadan sonra: armut=2 elma=4
referanstan sonra: armut=102 elma=104
```

İlk döngü `auto [ad, adet]` ile her elemanın kopyasını bağladı; `adet += 100` yalnız o
kopyaya yazdı, `stok` **kopyadan sonra** satırında değişmeden görünüyor. İkinci döngü
`auto& [ad, adet]` ile elemanların kendisine bağlandı; aynı `+= 100` bu kez `stok`un
kendisine ulaştı. **KT40.** Yapısal bağlamada da tip çıkarımının sınıfı köşeli parantezden
önceki `&`e bağlıdır: `auto [...]` kaynağı **aynen** bırakır, `auto& [...]` kaynağı
**değişti**rir — ikisi de aynı kayıt tipini, aynı isimlerle parçalıyor, fark yalnız o tek
karakterde.

## Okunabilirlik Dengesi

`auto` bir kısayoldur ama her yerde okunabilirliği artırmaz. Tip adı okura kaynağın ne
olduğunu, hangi işlemlerin geçerli olduğunu söylüyorsa yazılmalıdır: bir yineleyicinin
uzun şablon adı yerine `auto it` yazmak okuru rahatlatır, çünkü `it`in kendisi zaten bir
yineleyici olduğunu söylüyor. Ama bir işlevin dönüş tipi çağıran tarafın davranışını
belirliyorsa — örneğin dönen şey bir referans mı, bir kopya mı — bu bilgiyi `auto`nun
arkasına gizlemek okuru yanlış varsayıma iter. Bu dersin gösterdiği gibi, `auto` ile
`auto&` arasındaki fark derleyici için görünür bir `&` işaretidir, ama okuyucu için o
işareti fark etmek, koddaki kaynağın **aynen** mi kaldığını yoksa **değişti**ğini mi
kestirebilmesinin tek yoludur. Bu yüzden bir okuma değişkeninde `const auto&`, bir
elemanları değiştiren döngüde `auto&` yazmak; asıl tipin kendisi anlam taşıdığında da `auto`yu
atlayıp tipi olduğu gibi yazmak, kısayoldan ödün vermeden okunabilirliği korur.

M11/K04 (C++ Temelleri ve Nesne Tasarımı) bir ifadenin **hangi nesneyle** çalıştığını
ölçmüştü; oradaki `kopya` sınıfı bir **hedefi** adlandırıyordu — atamanın ya da yapıcının
yazdığı yeni nesneyi. Bu kursun `aynen` sınıfı ise bambaşka bir şeyi adlandırır: işlemin
**kaynağı**, yani zaten var olan, üzerinde çalışılan nesneyi. `for (auto x : v)` bir kopya
kurduğunda ortada tek bir işlem vardır; K04 o kopyanın hedefini sorardı, bu ders işlemin
kaynağa ne bıraktığını sorar. Aynı satır, iki farklı soruya iki farklı cevap verir.

## Sınırlayıcı Ölçüm

Bu dersin ölçtüğü şey, kapsayıcı gezinmesinde çıkarılan tipin kaynağa ne bıraktığıdır.
Aynı vektörü iki farklı döngüyle geziyoruz; başlıktaki tek fark bir `&` işareti.

```cpp
// auto-referans-ile-yazma.cpp — auto& dongusu kaynagi degistiriyor mu
#include <cstdio>
#include <vector>

int main() {
    std::vector<int> v{5, 7};
    auto once = v;

    for (auto& x : v) x *= 2;

    std::printf("auto& sonrasi:");
    for (int deger : v) std::printf(" %d", deger);
    std::printf("\n");
    std::printf("degisti mi: %s\n", v == once ? "hayir" : "evet");
    return 0;
}
```

```text
auto& sonrasi: 10 14
degisti mi: evet
```

```cpp
// auto-kopya-ile-okuma.cpp — auto kopya olusturuyor, kaynak degismiyor
#include <cstdio>
#include <vector>

int main() {
    std::vector<int> v{5, 7};
    auto once = v;
    int toplam = 0;

    for (auto x : v) {
        toplam += x;
        x *= 2;   // yalnizca kopyayi degistiriyor, v'ye ulasmiyor
    }

    std::printf("auto kopya:");
    for (int deger : v) std::printf(" %d", deger);
    std::printf(", toplam %d\n", toplam);
    std::printf("degisti mi: %s\n", v == once ? "hayir" : "evet");
    return 0;
}
```

```text
auto kopya: 5 7, toplam 12
degisti mi: hayir
```

**KT41.** `for (auto& x : v) x *= 2;` her elemana kaynağın kendisi üzerinden bağlanır;
`x *= 2` doğrudan `v`ye yazar, döngü sonunda `v` **değişti**. `for (auto x : v)` ise her
adımda bir kopya kurar; `x *= 2` yalnız o kopyayı değiştirir, `v` döngü sonunda **aynen**
kalır — `toplam` kopyalardan hesaplanmış olsa bile kaynağa hiçbir şey yazılmadı. Tip
çıkarımının sınıfı burada başlıktaki tek karakterle belirleniyor: derleyici `&`i görüp
referans mı kopya mı kuracağına karar veriyor, okuyucunun bunu satırın geri kalanından
çıkarması gerekiyor. Bu dersin sınıfı, `auto&` biçiminin verdiği sonuçla adlandırılır:
**değişti**.

## Özet

- Bu dersin merkezi ölçümünün sınıfı **değişti**: `for (auto& x : v) x *= 2;` kaynağın
  kendisine yazar, `for (auto x : v)` yalnız bir kopyayı değiştirir ve kaynağı **aynen**
  bırakır.
- `auto` bir ifadenin const'unu ve referansını düşürür; `auto&` referansı düşürmez,
  `const auto&` kopya almadan salt okur.
- `auto&&` bir iletme referansıdır: başlatıcı sol değerse `T&`, sağ değerse `T&&` çıkarır;
  bu davranış yalnız çıkarım yapılan bağlamlarda görülür.
- `decltype` bir ifadenin tipini olduğu gibi verir, referansı düşürmez; `decltype(auto)`
  bir işlevin dönüş tipini aynı kuralla çıkarır ve dönüş ifadesinin parantez içine
  alınması sonucu değere değil referansa çevirebilir.
- Yapısal bağlamada `auto [ad, adet]` kaynağı **aynen** bırakır, `auto& [ad, adet]`
  kaynağı **değişti**rir — fark yine köşeli parantezden önceki tek `&` işaretidir.
- Tip adını yazmak, o ad okura kaynağın davranışı hakkında bir şey söylediğinde
  gerekçelidir; aksi halde `auto` kısayolu okunabilirliği bozmaz.

## Kurs Kapanışı

Bu kurs boyunca on bir farklı işlemi aynı soruyla ölçtük: bir işlem kaynağa ne bırakıyor?
Aşağıdaki tablo her dersin ölçtüğü işlemi, kaynağa kalanı ve o dersin sınırlayıcı ölçümünü
özetliyor.

| Ders | Ölçülen işlem | Kaynağa kalan | Sınırlayıcı ölçüm |
| --- | --- | --- | --- |
| Akıllı İşaretçiler | `unique_ptr` taşındı | boş | `std::move` tek başına taşımaz; kaynak **aynen** kalır, taşıyan yapıcı ya da taşıyan atama çağrılmadıkça |
| Taşıma Semantiği | `std::string` taşındı | belirsiz | `const` nesnede `std::move` kopyalayan yapıcıya düşer, kaynak **aynen** kalır |
| Sıfır ve Beş Kuralı | Yıkıcılı sınıfta `std::move` | aynen | Aynı satır, sınıfın yazılışına göre iki farklı sınıfa düşer: **aynen** ya da **belirsiz** |
| Kopyalanamaz ve Taşınamaz Tipler | Kendi taşıyan yapıcısı | boş | `is_move_constructible_v<Kilit>` **hayır** — kopyalayan yapıcı silinmiş, taşıma hiç bildirilmemiş |
| Kapsayıcılar | `map`'te `operator[]` ile okuma | değişti | `const map`'te `operator[]` derlenmez; okumak için bile yazma izni ister |
| Yineleyiciler ve Geçerlilik | Silinen yineleyici | belirsiz | Aynı silme `std::list`'te yalnız silinen düğümün yineleyicisini geçersizleştirir, ötekiler **aynen** kalır |
| Algoritmalar | `std::sort` | değişti | `sort` ve `stable_sort` ikisi de **değişti**, ama eşit elemanların sırası yalnız birinde garanti |
| Sil–Kaldır Deyimi | `std::remove` sonrası kuyruk | belirsiz | C++20'nin serbest `std::erase`'i kuyruğa hiç dokunmadan doğrudan **değişti**ye götürür |
| Lambdalar ve Fonksiyon Nesneleri | `mutable` değerle yakalama | aynen | Aynı gövde üç farklı yakalamada üç sınıf verir: değer **aynen**, referans **değişti**, taşıma **belirsiz** |
| Aralıklar | Sol değerden görünüm | aynen | Sağ değerden kurulan görünüm taşıyan yapıcıyla kaynağı **boş**a çevirir |
| Tip Çıkarımı | `auto&` ile döngü | değişti | `auto` ile `auto&` arasındaki tek `&` kaynağı **aynen**den **değişti**ye çevirir |

**3 aynen · 3 değişti · 2 boş · 3 belirsiz; durumu söylenen 8, söylenmeyen 3.** Bu dağılım
tablodaki on bir dersin dağılımıdır ve kursun başında kurulan çekirdeğin dağılımıyla
birebir aynıdır: her işlem kaynağı ya olduğu gibi bırakır, ya değiştirir, ya sözleşmeyle
boşaltır, ya da değerini söylemeden bırakır ve ona ancak yeni bir değer verildikten sonra
bakılabilir.

Sıradaki kurs **Şablonlar ve Başarım**; şablonlar, eşzamanlılık ve başarım konularını
işliyor.
