C ++ 11'de "return {}" ifadesi ne anlama geliyor?


115

İfade ne

return {};

C ++ 11'de belirtin ve bunun yerine ne zaman kullanılacağını (söyleyin)

return NULL;

veya

return nullptr;

59
işlevin dönüş türünün varsayılan olarak oluşturulmuş bir örneğini döndürür.
Richard Hodges

Yoksa return;değeri olmayan basit mi?
i486

Hayır, tartışmanın da ortaya koyduğu gibi, işlevinizin bir şey döndürmesi (yani void dönüş türünde değil) ve yalnızca yazmanız bir derleme zamanı hatasıdır return; . Öte yandan return{};, bir dönüş türünüz varsa geçerlidir.
Pedia

@Pedia Her zaman değil, bazı nesneler oluşturmak için bağımsız değişkenler gerektirir
MM

Yanıtlar:


108

return {};"boş bir liste başlatıcıyla başlatılan işlevin dönüş türünden bir nesneyi döndür " anlamına gelir. Tam davranış, döndürülen nesnenin türüne bağlıdır.

Gönderen cppreference.com (OP ++ 11 C etiketlendiği çünkü ben C ++ 14 ve C ++ 17'de kuralları hariç; daha detaylı bilgi için linke bakınız):

  • Ayraçlı init listesi boşsa ve T varsayılan kurucuya sahip bir sınıf türü ise, değer başlatma gerçekleştirilir.
  • Aksi takdirde, T bir toplama türü ise, toplu başlatma gerçekleştirilir.
  • Aksi takdirde, T, std :: initializer_list'in bir özelleşmesiyse, T nesnesi, bağlama bağlı olarak, ayraçlı init listesinden doğrudan başlatılır veya kopyayla başlatılır.
  • Aksi takdirde, T'nin kurucuları iki aşamada ele alınır:

    • Std :: initializer_list'i tek bağımsız değişken olarak veya kalan bağımsız değişkenlerin varsayılan değerleri varsa ilk bağımsız değişken olarak alan tüm yapıcılar, std :: initializer_list türündeki tek bir bağımsız değişkene karşı aşırı yük çözümlemesi ile incelenir ve eşleştirilir
    • Önceki aşama bir eşleşme üretmezse, T'nin tüm oluşturucuları, yalnızca daraltılmayan dönüşümlere izin verilen kısıtlama ile, çaprazlı başlangıç ​​listesinin öğelerinden oluşan bağımsız değişkenler kümesine karşı aşırı yük çözümlemesine katılır. Bu aşama, bir kopya listesi başlatması için en iyi eşleşme olarak açık bir kurucu üretirse, derleme başarısız olur (not, basit kopya başlatmada, açık oluşturucular hiç dikkate alınmaz).
  • Aksi takdirde (T bir sınıf türü değilse), eğer parantezli init-list yalnızca bir öğe içeriyorsa ve T bir başvuru türü değilse veya öğenin türüyle uyumlu bir başvuru türü ise, T doğrudan daraltılmış dönüşümlere izin verilmemesi dışında başlatılmış (doğrudan liste başlatmada) veya kopyayla başlatılmış (kopya listesi başlatmada).

  • Aksi takdirde, T öğenin türüyle uyumlu olmayan bir başvuru türü ise. (referans sabit olmayan bir değer referansı ise bu başarısız olur)
  • Aksi takdirde, parantezli init listesinin hiç elemanı yoksa, T değeri başlatılır.

C ++ 11'den önce, a döndüren bir işlev için şunu std::stringyazmanız gerekirdi:

std::string get_string() {
    return std::string();
}

C ++ 11'de küme ayracı sözdizimini kullanarak türü tekrarlamanıza gerek yoktur:

std::string get_string() {
    return {}; // an empty string is returned
}

return NULLve return nullptrişlev bir işaretçi türü döndürdüğünde kullanılmalıdır:

any_type* get_pointer() {
    return nullptr;
}

Bununla birlikte, NULLC ++ 11'den beri kullanımdan kaldırılmıştır çünkü bu sadece bir tamsayı değerinin (0) takma adıdır, oysa nullptrgerçek bir işaretçi türüdür:

int get_int() {
    return NULL; // will compile, NULL is an integer
}

int get_int() {
    return nullptr; // error: nullptr is not an integer
}

91

Bu muhtemelen kafa karıştırıcıdır:

int foo()
{
  return {};   // honestly, just return 0 - it's clearer
}

Bu muhtemelen değil:

SomeObjectWithADefaultConstructor foo()
{
  return {};
  // equivalent to return SomeObjectWithADefaultConstructor {};
}

9
Öyleyse, dönüş türünün varsayılan bir kurucusu yoksa bu bir derleme zamanı hatasıdır, doğru mu?
Pedia

10
Dönüş türü, açık olmayan bir varsayılan kurucuya sahip olmayan ve bir toplam olmayan bir sınıfsa, bu bir derleme hatasıdır .
Oktalist

3
Türün bir initializer_listkurucusu varsa, varsayılan kurucu yoksa bu kullanılmaz mı?
celtschk

4
"muhtemelen kafa karıştırıcı"? Bu yüzden mi isimsiz bir ruh "C ++ olan o şişirilmiş müstehcenlik" den bahsediyor mu? Bunun sağladığı tuş vuruşlarında tasarruf, sunduğu açıklık eksikliği potansiyelini haklı gösterebilir mi? Bu samimi bir sorudur. Lütfen beni pratik örneklerle ikna edin.
MickeyfAgain_BeforeExitOfSO

4
return {}eşdeğer DEĞİLDİRreturn SomeObjectWithADefaultConstructor{};
MM

26

return {};bu {}, dönüş değeri için başlatıcı olduğu anlamına gelir . Dönüş değeri, boş bir listeyle liste olarak başlatılır.


C ++ Standardında [stmt.return] 'e dayalı olarak dönüş değeri hakkında bazı arka plan bilgileri aşağıda verilmiştir :

Değere göre dönen bir işlev için (yani dönüş türü bir başvuru değildir ve değildir void), dönüş değeri olarak adlandırılan geçici bir nesne vardır . Bu nesne returnifade tarafından yaratılır ve onun başlatıcıları return ifadesinde ne olduğuna bağlıdır.

Dönüş değeri, işlevi çağıran koddaki tam ifadenin sonuna kadar hayatta kalır; sınıf türüne sahipse, çağıran tarafından doğrudan kendisine bir başvuru bağlayarak ömrü uzatılmadığı sürece yıkıcısı çalışacaktır.

Dönüş değeri iki farklı şekilde başlatılabilir:


Tİşlevin dönüş türü olduğu varsayılırsa , şundan return T{};farklı olduğuna dikkat edin return {}: birincisinde, bir geçici T{}oluşturulur ve sonra dönüş değeri bu geçiciden kopyalanarak başlatılır.

TErişilebilir bir kopya / taşıma yapıcısı yoksa bu derleme başarısız olur , ancak return {};bu kurucular mevcut olmasa bile başarılı olur. Buna göre, return T{};kopya yapıcı vb. Yan etkilerini gösterebilir, ancak bu bir kopya seçim bağlamıdır, bu nedenle olmayabilir.


C ++ 14'te (N4140 [dcl.init.list] / 3) liste başlatmanın kısa bir özeti , burada başlatıcı boş bir listedir:

  • Bir Ttoplamsa, her üye, eğer varsa , küme ayracı veya ekolayzerinden başlatılır , aksi halde sanki {} (bu adımları yinelemeli olarak uygulayın).
  • Eğer Tbir kullanıcı tarafından sağlanan varsayılan kurucu ile bir sınıf tipi, yani kurucu denir.
  • Eğer Tbir dolaylı tanımlanmış ya da bir sınıf tipidir = defaulted varsayılan kurucu, amacı, sıfır başlatıldı ve sonra varsayılan yapıcı olarak adlandırılır.
  • Eğer Tbir a std::initializer_listise, dönüş değeri böyle boş bir listedir.
  • Aksi takdirde (yani T, sınıf dışı bir türdür - dönüş türleri dizi olamaz), dönüş değeri sıfır ile başlatılır.

Aggregate init önce gelir ve {}değer-init olan veya olmayan her üyeyi özyinelemeli olarak başlatır .
TC

@TC doğru, cppreference ile gittim ama "C ++ 14'e kadar" göz ardı ettim
MM

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.