Dönüş türü '?:' (Üçlü koşullu işleç)


208

İlk neden bir referans döndürüyor?

int x = 1;
int y = 2;
(x > y ? x : y) = 100;

İkincisi değil mi?

int x = 1;
long y = 2;
(x > y ? x : y) = 100;

Aslında, ikinci hiç derleme değildi - "ödev sol değeri değil".


1
hmm, ekmek pişirmek için özel bir durum bulmak gibi, buna bir kez gelmedi
Ulterior


İfadeye bir tür atamak, en az bir terimlik bir döküm anlamına geleceğinden, bu terim artık l-değeri olmaz.
Yves Daoust

Yanıtlar:


173

İfadelerin dönüş türleri yoktur, bir türü vardır ve - en son C ++ standardında bilindiği gibi - bir değer kategorisidir.

Bir koşullu ekspresyonu bir olabilir lvalue veya rvalue . Bu onun değer kategorisidir. (Bu bir şekilde basitleştirmedir, C++11çünkü lvalues, xvalues ​​ve prvalues ​​var.)

Çok geniş ve basit anlamda, bir lvalue bellekte bir nesneye atıfta bulunmaktadır ve bir rvalue zorunlu bellekte bir nesneye bağlı olabilir bir değerdir.

Bir atama sentezleme şey, olmalıdır tahsis edilir, böylece bir nesnenin bir değer atar lvalue .

Bir koşullu ekspresyonu için ( ?:) bir olduğu lvalue (yine geniş ve basit olarak), ikinci ve üçüncü işlenen olmalıdır Sol taraf aynı tip . Bunun nedeni, koşullu ifadenin tür ve değer kategorisinin derleme zamanında belirlendiği ve koşulun doğru olup olmadığının uygun olması gerektiğidir. İşlenen bir başka eşleştirmek için farklı bir türü dönüştürülmesi gerekir sonra koşullu ifade bir olamaz lvalue bir olmaz, bu dönüşüm sonucu lvalue .

ISO / IEC 14882: 2011 referansları:

3.10 [basic.lval] Değerler ve değerler (değer kategorileri hakkında)

5.15 [expr.cond] Koşullu işleç (koşullu ifadenin türü ve değer kategorisi için kurallar)

5.17 [expr.ass] Ödev ve bileşik ödev operatörleri (ödevin lh'lerinin değiştirilebilir bir değer olması gerekir)


3
Ve xvalue ve prvalue okurken (cevabınızdan önce onları duymamıştım beri) bu kullanışlı SO yazı ile karşılaştım: stackoverflow.com/questions/3601602/…
kabarık

an rvalue is just a value that may not necessarily be *attached* to an object in memory.Bunu daha basit bir şekilde açıklayabilir misiniz? . Ayrıca ne demek istiyorsun type and value *category*? Teşekkürler
Mr.Anubis

@SoulReaper: prvalue, xvalue, glvaluedeğer kategorileridir.
Xeo

@ Xeo Yardımı takdir ediyorum, ancak bir değer ile ne demek istediğini anlayabiliyor musunuz , sadece bellekteki bir nesneye iliştirilmiş olması gerekmeyen bir değerdir. ? örnek?
Mr.Anubis

@SoulReaper: Bence şeyler bahsediyor gibi true, this, enumdeğerlerini. Bu şeyler birer değerdir ("saf" değerler), ama hafızada yaşamazlar.
Xeo

57

Üçlü ?:ifadenin türü, ikinci ve üçüncü argümanının ortak türüdür. Her iki tür de aynı ise, geri başvuru alırsınız. Birbirlerine dönüştürülebilirlerse, biri seçilir ve diğeri dönüştürülür (bu durumda terfi edilir). Geçici değere (dönüştürülen / yükseltilen değişken) bir lvalue başvurusu döndüremediğiniz için, türü bir değer türüdür.


ancak y, x'den büyük, bu nedenle bu özel durum için promosyona gerek yok, y'ye referans verebilir. Hmm ... Ama katılıyorum, garip olurdu.
Yola

1
@ Mr.TAMER: Standardı araştırmayı tercih ederim. : <
Xeo

3
@Yola: Türler C ++ 'da bir derleme zamanı kavramı olduğundan, ifadenin gerçek dönüş değeri önemli değildir.
Xeo

1
Geri referans almazsınız, değer alırsınız.
Suma

1
@ Xeo: C ++ terminolojisinde olmasa da;)
Sebastian Mach

19

Bu bir döndüremez lvalue bunun dolaylı türünü desteklemek zorunda kalacak beri xtürüne uyacak şekilde y(her iki tarafı beri :aynı türden değildir), ve sahip olduğu ile geçici oluşturun.


Standart ne diyor? ( n1905 )

İfadeler 5.17 Atama ve bileşik atama işleçleri

5.17 / 3

İkinci ve üçüncü işlenenler farklı türlere sahipse ve ya (muhtemelen cv-nitelikli) sınıf türüne sahipse, bu işlenenlerin her birini diğerinin türüne dönüştürme denemesi yapılır. T1 tipi bir işlenen ifadesinin E1'in T2 tipi bir işlenen ifadesi E2 ile eşleşip dönüştürülemeyeceğini belirleme işlemi şu şekilde tanımlanır:

- E2 bir değerse: E1, örtüşmede referansın doğrudan bağlanması ( ) E1.

- E2 bir değerse veya yukarıdaki dönüşüm yapılamıyorsa:

- E1 ve E2 sınıf türüne sahipse ve temel sınıf türleri aynıysa veya biri diğerinin temel sınıfıysa: T2 sınıfı aynı türse veya E2'nin temel sınıfı ise E1, E2'ye dönüştürülebilir , Tl sınıfı ve T2'nin cv-niteliği, Tl'in cv-niteliği ile aynı cv-niteliği veya daha büyük bir cv-niteliğidir. Dönüştürme uygulanırsa, E1, hala orijinal kaynak sınıfı nesnesine (veya bunun uygun alt nesnesine) karşılık gelen T2 türündeki bir değerle değiştirilir. [ Not: yani bir kopya yapılmaz. - bitiş notu ] T1 tipi bir geçici belgeyi E1'den kopyala başlatarak ve bu geçici işlemi dönüştürülen işlenen olarak kullanarak.

Aksi takdirde (örneğin, E1veya E2 sınıf dışı bir türe sahipse veya her ikisinin de sınıf türü varsa, ancak alttaki sınıflar aynı değilse veya diğerinin temel sınıfı değilse): E1, E1 olabilirse, E2 ile eşleşebilir dolaylı olarak, E2 bir değer değerine (veya E2 bir değer ise, sahip olduğu tür) E2 ifadesinin sahip olacağı türe dönüştürülür.

Bu işlem kullanılarak, ikinci işlenenin üçüncü işlenenle eşleşip dönüştürülemeyeceği ve üçüncü işlenenin ikinci işlenenle eşleşip dönüştürülemeyeceği belirlenir. Her ikisi de dönüştürülebilirse veya biri dönüştürülebilirse, ancak dönüşüm belirsizse, program kötü biçimlendirilir. Hiçbiri dönüştürülemezse, işlenenler değişmeden kalır ve aşağıda açıklandığı gibi başka kontroller yapılır. Tam olarak bir dönüşüm mümkünse, bu dönüşüm seçilen işlenene uygulanır ve dönüştürülen işlenen bu bölümün geri kalanı için orijinal işlenen yerine kullanılır.


5.17 / 4

İkinci ve üçüncü işlenenler değerse ve aynı türe sahipse, sonuç bu türdendir ve bir değerdir ve ikinci veya üçüncü işlenen bir bit alanıysa veya her ikisi de bit ise, bir bit alanıdır. alanlar.


5.17 / 5

Aksi takdirde sonuç bir değerdir. İkinci ve üçüncü işlenenler aynı türe sahip değilse ve ya (muhtemelen cv-nitelikli) sınıf tipine sahipse, işlenenlere uygulanacak dönüşümleri (varsa) belirlemek için aşırı yük çözünürlüğü kullanılır (13.3.1.2, 13.6) . Aşırı yük çözünürlüğü başarısız olursa, program kötü biçimlendirilmiştir. Aksi takdirde, bu şekilde belirlenen dönüşümler uygulanır ve dönüştürülmüş işlenenler, bu bölümün geri kalanı için orijinal işlenenler yerine kullanılır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.