Bunun neden derlendiğini anlamıyorum


80

Kesinlikle bir şey eksik, ama neden bu derler (hem g ++ & clang ++ ile) anlamıyorum:

struct A
{
};
struct B
{
};

int main()
{
  A a(B);
}

Her şeyden önce, Bbir tür ... bir değer değil. Bu kodu nasıl yorumlamalıyım?



8
@alterigel Gerçekten mi? Bu durumda belirsizlik yoktur. Yalnızca bir işlev bildirimi olabilir. A a(B());Değişken tanımı veya işlev bildirimi olabilecek bir durum değildir .
ceviz

8
Hiçbir şeyi adlandırmasa bile , struct A{}; int main() { A(foo); } derleyicileri olduğu gibi bilmek şaşırtıcı olurdu foo.
Ayxan

20
@alterigel - bu en can sıkıcı çözüm değil . Bağlantı kurduğunuz sayfadaki örneklere bakın. Bu sadece bir işlev bildirimidir.
Pete Becker

3
@PeteBecker, ceviz zaten yukarıda yaptığına inanıyorum, bunun neden olmadığını iddia etmek yerine neden MVP olmadığını açıklamak daha iyi olabilir .
JPhi1618

Yanıtlar:


84

Bu, bir atür Bve döndürme argümanı alan adlı bir işlevin bildirimi olarak yorumlanır A.


5
İşte bu yüzden Most ve Vexing. Bir çözüm: (kötü inşaatı ortaya çıkardığı için aslında hiçbir şeyi A a{B};
çözmediği için değil

23
@ user4581301 - en sinir bozucu çözüm değil . Bu sadece bir işlev beyanıdır.
Pete Becker

23
Yani bu sadece çoğunlukla
rahatsız edici bir

11
Bu konuda en garip kısmı C ++ yuvalanmış işlev izin vermez, ancak olmasıdır gelmez bir işlev içinde bildirimleri izin verir.
The_Sympathizer

6
C ++ 'a yuvalanmış işlevler için destek eklemek için iyi bir motivasyon gibi geliyor; sadece yararlı olmazlardı, bu tuhaf siğilleri makul bir tasarıma dönüştürdüler :)
Jeremy Friesner

15

Bu, yalnızca bir adsız parametre türü adöndüren Ave alan bir işlev olduğunu bildiren bir işlev bildirimidir B.

İşlev tanımları yerine fonksiyon tanımlarına izin verildiğinden fonksiyon tanımlarına izin verilir.


13

Bu sorun en can sıkıcı çözüm olarak bilinir . Çizgi A a(B);, atürdeki bir nesneyi döndürme Ave adsız türdeki bir parametre alma adlı bir fonksiyonun bildirimi olarak yorumlanabilir B.

Bu sorunu önlemenin bir yolu , parantez yerine parantez kullanmaktan oluşan C ++ 11'de tanıtılan tek tip başlatma sözdizimini kullanmaktır: A a{B};bir hata döndürür. Çizgi şimdi B, değerle başlayan bir tür olan, başlatılan değişken bir bildirim olarak yorumlanır .

Daha fazla bilgi:

En Vexing Ayrıştırma: Nasıl Spot ve Hızlıca Fix


12
Bunun " en sinir bozucu ayrıştırma " olarak adlandırılması gerektiğini sanmıyorum . Bu sadece C'de de mevcut olduğu gibi olağan bir işlev bildirimidir. Çizgi sadece bir işlev bildirimi olabilir, başka hiçbir şey olmayabilir çünkü belirsizlik çözümü gerekmez. Bağlantınıza bakın. Örneklerin hepsi bundan farklı.
ceviz

3
Bu doğru olsa da, en sinir bozucu ayrıştırma ile ilgilidir. Sadece orijinal tipte olduğu gibi bir değişken veya bir yapıcı çağrısı yerine bir tür adının tek başına kullanıldığı bir yazım hatası da içeriyordu.
Miral

1
Evet, "En Vexing Ayrıştırma", söz konusu gerçek durum sadece "Biraz Vexing Ayrıştırma" olmasına rağmen yararlı bir cevaptır.
jpa

1
@wlanut: struct A { };Bazı derleyiciler izin verse bile boş yapılar standart C'de geçerli değildir. Diş tellerini bırakın ve orada bir sorun olmazdı. Ayrıca, C'de bildirme veya tanımlama struct Abir tür adı oluşturmaz A(önek olmadan kullanmanız structveya daha typedef struct A A;önce bir yere eklemeniz gerekir ). Ayrıca C'de işlev bildirimine alternatif bir ayrıştırma yoktur - kullanmak hiç bir zaman değişken bir tanım olamaz; her zaman bir işlev bildirimidir (veya geçersizdir). Sorudaki kod C'de geçerli değil.Astructtype name(...);
Jonathan Leffler
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.