ilk değer verme (initialization) – 1

C++ sentaksının en fazla zorluk içerdiği noktalardan biri ilk değer verme (initialization). Bu konuda dilin çok sayıda kuralı ve bu kurallara ilişkin kullanılan çok sayıda terim var. C++11 ve C++14 standartlarıyla getirilen farklılıklar ve eklemeler, bazı tanımların yeniden yapılması ve bazı tanımların değiştirilmesi, zaten fazlasıyla karışık olan bu konuyu daha da karışık hale getiriyor. Bu yazıda hem bu kuralları anlatmaya hem de bu terimleri mümkün olduğunca açıklamaya çalışacağım. Konunun kapsamı çok geniş olduğundan konuyu birkaç farklı yazı ile ele almayı planlıyorum.

Bir nesne hayata bir değerle gelir. Nesnenin hayata geldiği zaman alacağı değerin belirli (determined) ya da belirsiz (indetermined) olması kullanılan ilk değer verme sentaksının ne olduğuna bağlıdır. İlk değer verme konusunda kullanılan önemli terimler ve bu terimler için önerdiğim Türkçe karşılıklar şunlar:

Önce sıfırla başlatım (zero initialization) terimini ele alalım:

T bir tür olmak üzere T türünden bir nesnenin sıfırla başlatımı sonucunda şunlar olur:
i) T tekil (skalar) bir türden ise, nesne 0 tamsayı değerinin T türüne dönüştürülmesiyle elde edilen değeri alır. Örneğin int türden bir nesne bu durumda hayata 0 değeri ile başlarken double türden nesne hayata 0. değeri ile başlar. bool türden bir nesne hayata false değeri ile gelir. Bir gösterici (pointer) değişken bu durumda nullptr değeri ile hayata başlar.

ii) T, birlik (union) olmayan bir sınıf türü (class type) ise bu türden sınıf nesnesinin statik olmayan tüm veri öğeleri sıfırla başlatılır. Yine bu durumda nesneye ilişkin tüm taban sınıf alt nesneleri (base class subobjects) sıfırla başlatıma tabi tutulur.

iii) T bir birlik türü ise, birliğin isimlendirilmiş ilk öğesi sıfırla başlatıma tabi tutulur.

iv) T bir dizi türü ise dizinin tüm öğeleri (elements) üzerinde sıfırla başlatım uygulanır.

v) T bir referans türü ise bu referansa herhangi bir ilk değer verme işlemi yapılmaz.

Peki hangi durumlarda sıfırla başlatım uygulanır? Biraz karışık olan nokta burası. İlk değer verme sürecinin birden fazla işlemi ya da basamağı içerdiği bazı durumlarda ise sürecin ilk basamağı sıfırla başlatım olabilir. Yani bazı durumlarda nesne üstünde önce sıfırla başlatım uygulanır, sonra bunu ilk değer vermenin diğer basamakları ya da süreçleri izler. Aşağıdaki durumlarda bir nesne üzerinde sıfırla başlatım uygulanır:

1) static ya da thread_local ömür kategorisinde olan ve sabitle başlatıma (constant initializiation) konu olmayan tüm nesneler, başka türlü ilk değer verme işlemlerinden önce sıfırla başlatıma tabi tutulurlar. Bu tanımı biraz açalım: Öncelikle sabitle başlatım C++14 ile gelen bir sentaks yapısı. Bu terimi başka bir yazıda ele almak üzere şimdilik geçelim. Bu tanım statik ömürlü nesnelerin öncelikle sıfırla başlatıma tabi tutulduğunu anlatıyor. (İlk değer alma süreci içinde daha sonra başka işlemin yapılmayacağı anlamına gelmiyor).

2) Sınıf dışı türlerin değerle başlatımında, kurucu işlevi olmayan sınıf nesnelerinin öğelerinin değerle başlatımında, ilk değer verilmemiş bileşiklerin değerle başlatımında, değerle başlatım sekansının bir parçası olarak sıfırla başlatım uygulanır.

3) Bir karakter dizisine bir string sabiti ile ilk değer verildiğinde eğer string sabitindeki karakter sayısı ilk değer verilen dizinin boyutundan daha küçük ise dizinin kalan öğeleri sıfırla başlatıma tabi tutulur.

Şimdi aşağıdaki kodu inceleyelim:

Yukarıdaki kodda tanımlanan tüm nesnelerin ilk değerlerini alması aslında yukarıdaki tanımlara örnekler oluşturuyor:

double türden 5 öğeli global ga dizisi statik ömürlü olduğu için önce sıfırla başlatıma tabi tutuluyor. Bu durumda dizinin tüm öğeleri için sıfırla başlatım uygulanacak yani double türden dizi öğeleri 0. değerlerini alacaklar. Daha sonra uygulanması gereken “varsayılan başlatım” (default initialization) dizi üstünde herhangi bir işlem yapmayacak. İlk değer verme bu şekilde sonlanacak. Bu durum yukarıdaki 1 numaralı tanıma bir örnek.

int * türden gp göstericisi statik ömürlü olduğu için sıfırla başlatıma tabi tutuluyor. Böylece gp göstericisi nullptr değerini alacak. Daha sonra uygulanacak “varsayılan başlatım” nesneye bir değer vermeyecek. Bu durum da yine yukarıdaki 1 numaralı tanıma bir örnek.

standart string sınıfı türünden olan global s nesnesi varsayılan başlatıma (default initialization) tabi tutuluyor. Ancak statik ömürlü olan bu nesne üzerinde önce sıfırla başlatım uygulanacak. Veri öğeleri sıfırla başlatılmış olan s nesnesi daha sonra sınıfın varsayılan kurucu işlevi ile hayata getirilecek. Bu yine yukarıdaki 1 numaralı tanıma bir örnek.

Şimdi de main işlevi içimde yapılan bildirimlere bakalım:

Burada Data türünden d nesnesi değerle başlatılıyor. Data sınıfının kurucu işlevi derleyici tarafından yazılmış. Bu durumda değerle başlatılmış d nesnesinin tüm öğeleri değerle başlatılacak. int türden veri öğelerinin değerle başlatılması onların sıfırla başlatımı sonucunu doğuracak. Bu durum yukarıdaki 2 numaralı tanıma bir örnek.

Yukarıdaki tanımlamada, static anahtar sözcüğüyle tanıtılan int türden değişkene ival değişkeni ile ilk değer veriliyor. n değişkeni kopyalama ile başlatılacak (copy initiaization). Ancak n değişkeni statik ömürlü olduğundan nesne üzerinde önce sıfırla başlatım uygulanacak. Ardından nesnemiz ival değişkenin değerini alarak hayata gelecek. Bu durum yine yukarıdaki 1 numaralı tanıma bir örnek.

Yukarıdaki tanımlamda char türden str dizisine “BABA” string sabiti ile ilk değer veriliyor. Bu durumda dizinin kalan öğeleri üzerinde sıfırla başlatım uygulanacak. Bu durum yukarıdaki 3 numaralı tanıma bir örnek.

Notlar:

skalar (tekil) tür ne demek?
Aritmetik türler (tamsayı ve gerçek sayı türleri), numaralandırma (enum) türleri, göstericiler (pointers), üye işlev göstericileri (pointer to member functions), veri öğelerini gösteren gösterci türleri, nullptr_t türü, tekil türlerdir.

Necati Ergin

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

Bunlar da ilginizi çekebilir

Bir Cevap Yazın

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

Kod Eklemek İçin Okuyun