Glvalue, Rvalue Lvalue

Başlatan mr.engineer, 05 Nisan 2021, 12:40:38

mr.engineer

Merhaba, C++ da value category diye  lvalue, xvalue, prvalue, glvalue terimlerini içeren bir konu var. Anladığım kadarıyla lvalue memory'de yer kaplamalı. PR value ise yer kaplamamalı sabit bir değer belirtmeli. Yani sabit bir sayı veya int foo() şeklinde bir fonksiyon. Anlamadığım yerler ise;

1. ++a lvalue oluyorken, a++ nasıl pr value oluyor?

2. a.*mp, burada a rvalue ve mp pointer to data member ise lvalue oluyormuş. Bu nasıl oluyor. a burada nasıl rvalue olabiliyor? Bunun örneği nedir? 

3. xvalue tam olarak nedir? Bir yerde rvalue reference'lar için kullnılıyor yazmış başka bir yerde farklı bir sey yazmış.



C++ 'de yeni olan birinin bunları anlaması gerekiyor mu? Her şeyi bilmediğimden anlayamadım gibi geliyor.

Tagli

Ben de yeni yeni C++ öğrenip kullanmaya başladım. Bu konular benim de kafama çok girmedi. Ama başlangıçta her şeyi yalayıp yutmak gerekmiyor. C++ dipsiz kuyu gibi zaten. Yerinde de durmuyor, son yıllarda zırt pırt yeni standartlar çıkıyor. Ben STM32 için C++17 kullanıyorum ama tüm özelliklerini bilip kullandığımı söyleyemem tabi.

rvalue kabaca geçici değer demek, ya da ben o kadarını anlayabildim. rvalue olan bir şeyin yakın zamanda (mesela o komutun çalışmasının ardından) ömrü sona erecek demektir. Bunlar genelde C++11 ile birlikte gelen move işlemleri ile ilgili. Uygulanabildiği yerlerde ciddi performans artışı sağlıyor. Move işlemlerinin ana fikri, zaten yok olacak bir nesnenin heap üzerinde saklanan verilerini çalmak. Böylece tekrardan yer ayırma ve kopyalama işlemlerinden kaçınılmış oluyor.
Gökçe Tağlıoğlu

brandice5

Bu konular @Tagli'nın da dediği gibi performansla ilgili konular. Başlangıç seviyesi için çok derine inmek gerekir mi? tartışılır.

Mesela C++11 ile std::move getirildi. Bunu şöyle düşünebilirsin, elinde iki tane bardak var, biri dolu biri boş.
Sen dolu bardaktaki suyu boş bardağa aktarmak istiyorsun. std::move dan önce yapılan işlem, dolu bardaktaki suyu boş bardağa boşaltmaktı, yani kopyalama. Eğer bardağın baya büyükse bu dökme yani kopyalama işlemi ekstra zaman alıyordu yani performans olumsuz etkileniyordu.

İşte std::move ile bu bardaktan bardağa boşaltma (kopyalama) işlemi ortadan kaldırıldı. Şu an yapılan işlem boş bardağı yok edip, yerine direkt dolu bardağı koymak (move).
Yani kopyalama ile zaman kaybetmek yok, ve suyun miktarından bağımsız (isterse bir sürahi olsun).

volkanunal

1.sorununuz cevabı aslında C++ ile ilgili değil, POD (Pre-Post Increment) konusu standartlarda belirtilmiş.

The pre-increment should act as if the object was incremented before the expression and be usable in this expression as if that happened. Thus the C++ standards comitee decided it can also be used as an l-value.

The post-increment should increment the POD object and return a copy for use in the expression (See n2521 Section 5.2.6). As a copy is not actually a variable making it an l-value does not make any sense.



Örnek vermek gerekirse.
a++ = 2;

Yukarda bulunan kod hata olarak karşımıza çıkacaktır. Çünkü ifadenin bir kopyası döndürülmekte.

++a = 2;

Yukarda bulunan kod ise derlenecektir. Çünkü ifadenin this pointeri(yani kendisi) dönmekte.

Tabi değer kategori konusunda C ve C++ farklılıklar bulunmakta.


Bende C++ öğrenmeye çalışıyorum, şurada notlarımı paylaşıyorum (Ders 3 içerisinde bu konuda detaylı notları paylaştım.)
https://engineeringvolkan.wordpress.com/2021/02/07/c-kursu-notlarim/



Primum nil nocere

mr.engineer

Right left value konusu C'de de vardı ama pek önemi yoktu ya da ben öyle zannediyordum fakat C++'da işler farklıymış:)
Teşekkürler cevaplar için.
@volkanunal notlar güzel olmuş emeğine sağlık.

mr.engineer

Alıntı yapılan: volkanunal - 05 Nisan 2021, 13:40:341.sorununuz cevabı aslında C++ ile ilgili değil, POD (Pre-Post Increment) konusu standartlarda belirtilmiş.

The pre-increment should act as if the object was incremented before the expression and be usable in this expression as if that happened. Thus the C++ standards comitee decided it can also be used as an l-value.

The post-increment should increment the POD object and return a copy for use in the expression (See n2521 Section 5.2.6). As a copy is not actually a variable making it an l-value does not make any sense.



Örnek vermek gerekirse.
a++ = 2;

Yukarda bulunan kod hata olarak karşımıza çıkacaktır. Çünkü ifadenin bir kopyası döndürülmekte.

++a = 2;

Yukarda bulunan kod ise derlenecektir. Çünkü ifadenin this pointeri(yani kendisi) dönmekte.


Burası ilginç. C'de ikisi de derlenmiyor:) İkisi de right value galiba. Dediğin gibi standarda bakmak lazımmış. Ben bir mantık göremedim ama C++ çalışabilmesinin de sebebi vardır heralde.

Tagli

a++ rvalue oluyor çünkü ++ operatörü uygulanmadan önceki hali o komutta (expression?) kullanılıyor ve sonra yok ediliyor. a'nın sadece ++ uygulandıktan sonraki yeni hali hayatta kalıyor.
Gökçe Tağlıoğlu