ifade değer kategorileri (expression value categories) – 1

C++11 öncesi bir ifade (expression) ya sol taraf değeri (lvalue) ya da sağ taraf değeri (rvalue) olabiliyordu. C++11 ile birlikte taşıma semantiğinin (move semantics) dile eklenmesiyle ifade değer kategorileri de fazlalaştı. Artık ifade değer kategorilerimiz şunlar:

glvalue – generalized lvalue (genelleştirilmiş sol taraf değeri)
rvalue (sağ taraf değeri)
lvalue (sol taraf değeri)
xvalue /eXpiring value (gidici değer)
prvalue / pure rvalue (saf sağ taraf değeri)

Aşağıda bu kategoriler arasındaki hiyerarşik ilişkiyi gösteren bir diyagram görüyorsunuz:

C++ Dili İfade Kategorileri
C++ Dili İfade Kategorileri

C++11’e göre bir ifade lvalue, xvalue ya da prvalue kategorilerinden birinden olmak zorunda. Bunlara birincil (primary) ifade değeri kategorileri deniyor. Örneğin bir ifade hem lvalue hem xvalue olamıyor. Ya da bir ifade hem xvalue hem prvalue olamıyor.
glvalue kategorisi lvalue ve xvlaue ifadelerinin birlikte oluşturduğu kategori. Bir ifade lvalue ya da xvalue ise aynı zamanda glvalue değer kategorisinde.
rvalue kategorisi xvalue ve prvalue ifadelerinin oluşturduğu kategori. Bir ifade xvalue ya da prvalue ise aynı zamanda rvalue değer kategorisinde.

Diyagramdan da görebildiğiniz gibi bir xvalue ifadesi hem glvalue hem de rvalue kategorisinde kabul ediliyor. Aynı hiyerarşik yapıyı bu kez de farklı bir biçimde gösterelim:

Dilin sentaks kuralları söz konusu olduğunda ifade değer kategorileri büyük önem taşıyor. Belirli yerlerde belirli değer kategorilerinden ifadelerin kullanılmasının zorunlu olduğu durumlar var. Ayrıca derleyicimizin derleme işlemi sonucunda bize verdiği bulgu iletilerinde (diagnostic messages) ifade değer kategorileri sıkça karşımıza çıkıyor.

Bu yazımızda lvalue (sol taraf değeri) kategorisini inceleyeceğiz. Diğer değer kategorilerini bu serinin başka yazılarında ele alacağız.

lvalue (sol taraf değeri)

Belirli bir kimliğe sahip, bellekte bir yere ilişkin olan, bir nesneye ya da bir işleve karşılık gelen ve taşınamayan ifadeler sol taraf değeri olarak niteleniyor. Aşağıdaki ifadeler sol taraf değeri:

Kendi bilinirlik alanı (scope) içinde kullanılan bir değişken ya da işlev ismi türü ne olursa olsun bir sol taraf değeri kabul ediliyor. Değişkenin bildirimdeki türü sağ taraf referansı olsa da değişkenin ismiyle oluşturulan ifadeler yine sol taraf değeri:

Yukarıdaki bildirimlere bağlı olarak kullanılabilecek

ifadesi bir işlev ismi olduğundan bir sol taraf değeri.

bir değişken ismi olduğundan bir sol taraf değeri.

bir sağ taraf referansı olarak bildirilmiş, ancak bir isim olduğundan sol taraf değeri.

Nesnenin const ya da constexpr anahtar sözcükleriyle tanımlanmış olması bir sol taraf değeri olmasını engellemiyor:

Yukarıdaki bildirimlere bağlı olarak kullanabilecek ya da y ifadeleri sol taraf değeri olarak ele alınacak.

Geri dönüş değeri türü referans olan işlevlere yapılan çağrıların oluşturduğu ifadeler sol taraf değeri. Çağrıların işleç yüklemesi (operator overloading) mekanizmasıyla gerçekleştirilmiş olması bu durumu değiştirmiyor:

Yukarıdaki bildirim ve tanımlamaların bilinirlik alanında bulunan bir işlev içinde kullanılan bazı ifadelere bakalım:

ifadesi bir sol taraf değeri. Çünkü bu işlev bir referansa geri dönüyor.

ifadesi bir sol taraf değeri. Çünkü burada derleyicinin çağıracağı operator= işlevinin geri dönüş değeri bir referans.

ifadesi bir sol taraf değeri. Çünkü çağrılan önek operator++ işlevi referans döndürüyor.

ifadesi bir sol taraf değeri. Çünkü çağrılan gloabal operator<< işlevinin geri dönüş değeri referans.

ifadesi bir sol taraf değeri. Çünkü çağrılan global getline işlevinin geri dönüş değeri bir referans.

Doğal (built-in) türlerden terimlere sahip atama ve işlemli atama işleçleriyle oluşturulan ifadeler sol taraf değeri kabul ediliyor. Örneğin a, b, c int türden değişkenler olmak üzere

iafadeleri sol taraf değeri.

Terimleri doğal (built-in) türlerden olan önek ++ ve önek — işleçlerinin oluşturduğu ifadeler sol taraf değeri. Örneğin a ve b int türden değişkenler olmak üzere

ya da

ifadeleri sol taraf değeri.

Bir dizge sabiti (string literal) örneğin

bir sol taraf değeri.

İçerik (dereferencing) işlecinin terimi doğal türlerden bir gösterici (pointer) ise oluşturulan ifade bir sol taraf değeri:

Köşeli parantez (subscript) işlecinin doğal türleri terim olarak alarak oluşturduğu ifade bir sol taraf değeri.

a bir dizi olmak üzere (C++11’e göre sağ taraf değeri olan dizi değil ise) yukarıdaki ifade bir sol taraf değeri.

p gerçek bir gösterici değişken (akıllı gösterici değil) olmak üzere yukarıdaki ifade bir sol taraf değeri.

Bir sınıf nesnesinin öğesine erişme ifadesi

Burada m bir numaralandırma ismi değil ise
m static olmayan bir işlev ismi değil ise,
a bir sağ taraf değeri ve m referans türlerinden olmayan static olmayan bir veri öğesi değil ise, bir sol taraf değeri.

Gösterici yoluyla öğeye erişme ifadesi

p bir doğal (built-in) gösterici olmak üzere, m‘nin bir numaralandırma ismi ya da static olmayan bir üye işlev ismi olmaması durumunda bir sol taraf değeri.

Öğe göstericisi yoluyla öğeye erişme ifadesi

a bir sol taraf değeri ve mp bir sınıf öğesine öğe gösterici ise, bir sol taraf değeri kabul ediliyor;

p bir doğal gösterici ve mp bir sınıf öğesine öğe gösterici ise yukarıdaki ifade bir sol taraf değeri.

Virgül işleciyle oluşturulmuş bir ifadede sağ terim bir sol taraf değeri ise ifade sol taraf değeridir. Yukarıdaki ifadede b sol taraf değeri ise ifade sol taraf değeri.

Koşul işlecinin ikinci ve üçüncü terimleri sol taraf değeri ise koşul işlecinin oluşturduğu ifade sol taraf değeri olarak kabul ediliyor:

Yukarıdaki ifadede b ve c sol taraf değerleri ise ifade sol taraf değeri.

Bir sol taraf referansı türüne yapılan dönüştürme ifadesi, örneğin

sol taraf değeri.

Sol taraf değeri ifadelerine ilişkin önemli bazı kuralları bilmemiz gerekiyor:

Bir sol taraf değeri ifadesinin adres işleci (&) ile adresinin alınması geçerli.
Değiştirilebilir bir sol taraf değeri ifadesi (modifiable lvalue) atama ya da işlemli atama işleçlerinin sol terimi olabilir.
Bir sol taraf değeri ifadesi bir sol taraf referansına (lvalue reference) ilk değer verici ifade olarak kullanılabilir.

 

Share

Necati Ergin

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

Bunlar da ilginizi çekebilir

Kod Eklemek İçin Okuyun
Eklemek istediğiniz kodları lütfen aşağıdaki “pre” kodları arasında yazınız.
<pre class="lang:c++ decode:true ">
--yazacağınız kodlar--
</pre>
(buradan kopyalayarak kullanabilirsiniz)