auto belirleyicisi

C++11 standartlarıyla gelen en önemli eklentilerden biri auto belirleyicisidir. auto belirleyicisi ile tanıtılan bir değişkenin tür bilgisini derleyici, derleme zamanında yapacağı bir çıkarımla anlar.
C++11 standartları öncesinde tanımlanan değişkenlerin tür bilgisi belirtilmek zorundaydı:

Yukarıdaki kodda, ival int türden bir değişkendir.
iptr, int türden bir nesneyi gösteren gösterici değişkendir. Yani iptr, int * türündendir.
fp, geri dönüş değeri int*, parametre değişkeni double * türden olan bir işlevin adresini tutacak işlev göstericisidir.

auto belirleyicisi ile değişkene ilişkin tür bilgisinin derleyicinin çıkarımıyla belirlenmesi sağlanabilir:
Bunun için tanımlanan değişkene bir ifade ile ilk değer verilmelidir:

Derleyici bu durumda x değişkeninin türünü, ilk değer veren ifadenin türüne bakarak anlar:

ival değişkenine ilk değer veren ifade ne?

Bu ifadenin türü ne?
int
O zaman ival int türden.

iptr değişkenine ilk değer veren ifade ne?

Bu ifadenin türü ne?
int *
O zaman iptr,  int * türünden.

fp değişkenine ilk değer veren ifade ne?

Bu ifadenin türü ne?

O zaman fp değişkeni int *(*)(double *) türden bir işlev göstericisi.

Derleyicinin yaptığı bu çıkarım çok daha karmaşık olabilir:

İlk değer veren ifade ne?

Bu ifadenin türü ne?

O zaman iter, vector<list<int *>>::const_reverse_iterator türünden.

auto anahtar sözcüğü tanımlanan değişkene ilk değer vermek zorunludur. Örneğin:

auto belirleyicisi ile tanıtılan bir değişkenin türü bazı durumlarda ilk değer veren ifadenin türü ile tam olarak aynı olmaz:
İlk değer veren ifadede özellikle iki noktaya dikkat etmek gerekir:

i) İlk değer veren ifade olarak bir referans isim kullanılırsa burada referanslık dikkate alınmaz. Referans ismin yerine geçtiği nesnenin türü esas alınır.
ii) İlk değer veren ifadede kendisi const (top level const) bir nesne kullanılırsa buradaki const‘luk tür çıkarımında dikkate alınmaz. Örneklere bakalım:

Yukarıdaki kodda tanımlanan x değişkenine cdval değişkeni ile ilk değer verilmiştir. cdval,  const bir değişken olmasına karşın, tür belirlemesinde const‘luk göz önüne alınmaz. x değişkeni double türdendir.

cdr, const bir nesnenin yerine geçen referans bir isimdir. y değişkeninin türünün belirlenmesinde cdr‘nin referanslığı ve const‘luğu dikkate alınmaz. y değişkeni double türdendir.

z değişkenine ilk değer veren ifadenin türü int * olduğundan z değişkeni int * türündendir.

t değişkenine ise  &cival ifadesi ile ilk değer verilmiştir. const bir nesnenin adresi const int * türündendir. Buradaki const‘luk düşük seviyeli (low level) const‘luktur ve tür bilgisine dahil edilir.

auto anahtar sözcüğünü kullanarak kendisi const bir nesne oluşturulmak istenirse bu durumda auto belirteci ile const belirteci birlikte kullanılmalıdır:

auto ile tanıtılan değişkeninin bir referans olarak çıkarımının yapılması için auto anahtar sözcüğü ile birlikte & bildirgeçi (declarator) kullanılmalıdır. Bu durumda referansa ilk deger verme konusundaki kurallar geçerli olur:

Burada özellikle r1 referans isminin tanımına dikkat edilmelidir. auto & olarak tanıtılan isme kendisi const bir nesne ile ilk değer verildiğinde kendisi const‘luk göz ardı edilmez. cival, const int oluğundan r1 de cival değişkenine bağlanmış bir const referanstır.

r2 referans ismin tanımı geçerli değildir. İlk değer veren ifade bir sabit ifadesidir. const olmayan bir referansa bir sabit ifadesiyle ilk değer verilemez.

r3 referans isminin tanımında const anahtar sözcüğü kullanılmıştır. const bir referans bir sabit ifadesine bağlanabilir. Tanımlama geçerlidir.

İlk değer verici olarak bir dizi ismi kullanıldığında tanıtılan varlığın türü & bildirgecinin kullanılıp kullanılmamasına göre farklılık gösterir:

Yukarıdaki kodda auto anahtar sözcüğü ile tanıtılan x değişkeninde & bildirgeci kullanılmadığından dizi ismi dizinin adresine dönüştürülür (array to pointer conversion). x değişkeni int * türündendir.
Ancak y isminin tanıtımında & bildirgeci kullanıldığından dizi ismi dizinin adresine dönüştürülmez. y ismi 10 öğeli a dizisine bağlanmış bir referanstır. Yani y‘nin türü int (&)[10] türüdür.

Bir dizge (string literal) ile ilk değer verirken de benzer durum söz konusudur:

Yukarıdaki kodda auto anahtar sözcüğü ile tanıtılan x değişkeninde & bildirgeci kullanılmadığından dizge derleyicinin içsel olarak oluşturduğu const dizinin adresine dönüştürülür. x değişkeni const char * türündendir.
Ancak y isminin tanıtımında & bildirgeci kullanıldığından dizgenin adresine dönüşüm yapılmaz. y ismi 5 öğeli char türden const bir diziye bağlanmış bir referanstır. Yani y‘nin türü const char (&)[5] türüdür.

İlk değer verici olarak bir işlev ismi kullanıldığında da yinr tanıtılan varlığın türü & bildirgecinin kullanılıp kullanılmamasına göre farklılık gösterir:

Yukarıdaki kodda func işlevi içinde auto anahtar sözcüğü ile tanıtılan x değişkeninde & bildirgeci kullanılmadığından işlev ismi işlevin adresine dönüştürülür (function to pointer conversion). x değişkeni

türündendir.
Ancak isminin tanıtımında & bildirgeci kullanıldığından işlev ismi işlevin adresine dönüştürülmez. y ismi, foo işlevine bağlanmış bir referanstır. Yani y‘nin türü

türüdür.

Tek bir deyimde virgüllerle ayrılmış liste kullanılabilir:

Referans ya da gösterici bildirgeçleri (declarator) yalnızca bildirilen ismi niteler ve bildirimde kullanılan baz türe ilişkin değildir.
Bu durumda tüm ilk değer vericiler tutarlı türler sunmalıdır:

Yukarıdaki kodda r3  değişkenine ival ile ilk değer verildiğinden r3, int & türündendir. Bu durumda iptr değişkeni de int * türündendir. int * türünden olan iptr değişkenine &ci ifadesiyle yani const int * türden bir ifadeyle ilk değer verilmesi geçersizdir.

C++11 ile gelen aralık tabanlı for döngülerinde de (range based for loop) auto belirteci yaygın olarak kullanılır:

Burada auto belirteci ile tanıtılan döngü değişkeni, kapta (container) tutulan öğelerin türündedir. Tanıtılan döngü değişkeni bir referans isim olmadığından kapta tutulan öğenin kendisi değildir. Şüphesiz kopyalama yüzünden maliyet referans isim kullanılmasına göre daha yüksektir.

Tanıtılan ismin kapta tutulan öğenin kendisinin yerine geçmesi isteniyorsa & bildirgeci kullanılmalıdır:

Kap salt okuma amaçlı olarak dolaşılacak ise hem kodun anlaşılırlığını sağlamak hem de kaptaki öğeleri yanlışlıkla değiştirmeye karşı korumak amacıyla const referanslar kullanılmalıdır:

C++11’de bir değişkene farklı  biçimlerde ilk değer verilebilir:

Yukarıdaki kodda int türden olan x, y, z, ve t değişkenlerine sırasıyla 10, 20, 30 ve 40 ilk değerleri verilmiştir. Bu tanımlamalarda auto belirleyicisi kullanılabilir:

Yukarıdaki tanımlalamalardaki x, y ve z değişkenleri int türden iken t değişkeni int türden değildir. t değişkeni std::initializer_list<int> türündendir.

Ancak aşağıdaki bildirim geçerli değildir:

auto belirleyicisi ile tanıtılan değişkene küme parantezi içinde bir liste ile ilk değer verildiğinde liste içindeki öğelerin tümünün aynı türden olması zorunludur.

auto belirleyicisinin önemli bir kullanımı da lambda ifadeleriyle ilgilidir. Derleyici bir lambda ifadesi ile karşılaştığında içsel bir sınıf (closure) oluşturur. Bu sınıf türünden isimlendirilmiş bir nesne oluşturmak için auto belirleyicisi kullanılabilir:

Yukarıdaki kodda f değişkeni derleyicinin lambda ifadesi sonucu oluşturduğu içsel sınıf türündendir.

Sonuç olarak  auto belirleyicisini kullanmanın aşağıdaki avantajlarından söz edilebilir:

  • Tanımlanan değişklenlere ilk değer vermemek yüzünden oluşan kodlama hataları önlenmiş olur.
  • Betimlemesi uzun karmaşık türlerden değişkenleri tür bilgilerini yazarak tanımlamak hem zahmetli hem de hataya açıktır. Böyle durumlarda auto belirleyicisini kullanmak kolaylık sağladığı gibi hata yapma riskini azaltır.
  • auto belirleyicisi ile tanıtılan değişkene İlk değer veren ifadenin türü değişse de değişkenin tanımını değiştirmek gerekmez.
  • auto belirleyicisi anahtar sözcüğünün kullanımıyla lambda ifadeleriyle oluşturulan sınıf türlerinden isimlendirilmiş nesneler tanımlamak mümkün hale gelir.

Necati Ergin

C ve Sistem Programcıları Derneğinde eğitmen olarak çalışıyor.

Bunlar da ilginizi çekebilir

auto belirleyicisi” için 3 yorum

  1. int ival = 20;
    const int cival = 10;
    auto x = cival, &r1 = ival; // x int; r1 ise int&
    auto &r2 = cival, *cptr = &cival; // r2 const int&; cptr const int *
    auto &r3 = ival, *iptr = &ci; // geçersiz
    ———————————————————————————-
    *iptr = &ci den kastedilen cival mi?
    yazım yanlışı mı var?

  2. Bu yazılardan anladımki cdernek cini şişeden çıkmış.
    Acaba neden? Şimdi çıktı?

    Biraz geç kalmadı mı çıkmakta?
    ilginç

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Kod Eklemek İçin Okuyun