मुझे समझ नहीं आता कि यह क्यों संकलित है


80

मुझे निश्चित रूप से कुछ याद आ रहा है, लेकिन मुझे समझ नहीं आ रहा है कि यह संकलन (g ++ और clang ++ दोनों के साथ) क्यों है:

struct A
{
};
struct B
{
};

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

सबसे पहले, Bएक प्रकार है ... एक मूल्य नहीं है। मुझे इस कोड की व्याख्या कैसे करनी चाहिए?



8
@alterigel क्या यह वास्तव में है? इस मामले में कोई अस्पष्टता नहीं है। यह केवल एक फ़ंक्शन घोषणा हो सकती है। यह वह नहीं है A a(B());जो एक चर परिभाषा या फ़ंक्शन घोषणा हो सकती है।
अखरोट

8
आपको यह जानकर हैरानी होगी कि struct A{}; int main() { A(foo); } जैसा कि fooकुछ भी नाम नहीं है , वैसे ही संकलन है
अयक्सन

20
@alterigel - यह नहीं सबसे अप्रिय पार्स। उस पृष्ठ के उदाहरण देखें जिसे आपने लिंक किया था। यह केवल एक फ़ंक्शन घोषणा है।
पीट बेकर

3
@PeteBecker, यह समझाने के लिए बेहतर हो सकता है कि यह एमवीपी क्यों नहीं है क्योंकि यह केवल जोर देकर कहता है कि यह नहीं है, जो मुझे लगता है कि अखरोट पहले से ही ऊपर था।
जेपी 1618

जवाबों:


84

इसे एक फ़ंक्शन नाम की घोषणा के रूप में व्याख्या की जाती है a, जो प्रकार Bऔर रिटर्न का एक तर्क लेता है A


5
और इसीलिए यह Most और Vexing है। एक समाधान: (ऐसा नहीं है कि यह वास्तव में कुछ भी हल करता है क्योंकि यह खराब निर्माण को उजागर करता है)A a{B};
user4581301

23
@ user4581301 - यह नहीं सबसे अप्रिय पार्स। यह केवल एक फ़ंक्शन घोषणा है।
पीट बेकर

23
तो यह पता चला है कि यह केवल एक सबसे अधिक
डरावनी तोता है

11
इसके बारे में अजीब बात यह है कि सी ++ नेस्टेड कार्यों की अनुमति नहीं है, लेकिन है है एक समारोह के अंदर घोषणाओं अनुमति देते हैं।
the_Sympathizer 12

6
सी ++ के लिए नेस्टेड कार्यों के लिए समर्थन जोड़ने के लिए एक अच्छी प्रेरणा की तरह लगता है; न केवल वे उपयोगी होंगे, वे इस अजीब मस्सा को एक उचित डिजाइन में बदल देंगे :)
जेरेमी फ्रेज़र

15

यह केवल एक फ़ंक्शन डिक्लेरेशन aहै जो फ़ंक्शन को वापस करने Aऔर एक अनाम पैरामीटर को टाइप करने की घोषणा करता है B

यह मान्य है क्योंकि फ़ंक्शन परिभाषाओं के विपरीत फ़ंक्शन घोषणाएँ फ़ंक्शन परिभाषाओं के भीतर अनुमत हैं।


13

इस मुद्दे को सबसे अधिक डरावने पार्स के रूप में जाना जाता है । लाइन A a(B);को एक aप्रकार के ऑब्जेक्ट को लौटाने Aऔर एक अनाम पैरामीटर के प्रकार का नाम देने वाले फ़ंक्शन की घोषणा के रूप में व्याख्या की जा सकती है B

इस समस्या से बचने का एक तरीका यूनिफ़ॉर्म इनिशियलाइज़ेशन सिंटैक्स का उपयोग करना है जो C ++ 11 में पेश किया गया था, जिसमें कोष्ठक के बजाय ब्रेसिज़ का उपयोग करना शामिल है: A a{B};एक त्रुटि देता है। लाइन को अब एक वैरिएबल डिक्लेरेशन के रूप में समझा जाता है B, जो एक वैल्यू के बजाय एक प्रकार है।

यहाँ अधिक जानकारी है:

मोस्ट वैक्सिंग पार्स: हाउ टू स्पॉट इट एंड फिक्स इट क्विकली


12
मुझे नहीं लगता कि इसे " सबसे अधिक डरावनी तोता " कहा जाना चाहिए । यह केवल एक सामान्य कार्य घोषणा है क्योंकि यह भी सी में मौजूद है। कोई अस्पष्टता संकल्प आवश्यक नहीं है क्योंकि लाइन केवल एक फ़ंक्शन घोषणा हो सकती है, और कुछ नहीं। अपने लिंक को देखो। उदाहरण सभी इससे अलग हैं।
अखरोट

3
जबकि यह सच है, यह सबसे अधिक डरावने पार्स से संबंधित है। यह सिर्फ इतना है कि इसमें एक टाइपो भी शामिल है जहां एक प्रकार का नाम एक चर या एक निर्माता कॉल के बजाय अकेले उपयोग किया गया था, जैसा कि शायद मूल इरादे था।
मिरल

1
हाँ, "मोस्ट वैक्सिंग पार्स" इस मामले में एक उपयोगी उत्तर है, भले ही प्रश्न में वास्तविक मामला सिर्फ "थोड़ा सा Vexing Parse" हो।
जपा

1
@ वेलनट: खाली संरचना struct A { };मानक सी में मान्य नहीं हैं, भले ही कुछ संकलक उन्हें अनुमति दें। ब्रेसेस ड्रॉप करें और वहां कोई समस्या नहीं होगी। इसके अलावा, सी में, घोषित करने या परिभाषित करने से struct Aएक प्रकार का नाम नहीं बनता है A(आपको इसके साथ उपसर्ग करना होगा struct, या typedef struct A A;कहीं उपसर्ग के Aबिना उपयोग होने से पहले जोड़ना होगा struct)। सी में भी, फ़ंक्शन घोषणा के लिए कोई वैकल्पिक पार्स नहीं है - type name(...);बस का उपयोग करके कभी भी एक चर परिभाषा नहीं हो सकती है; यह हमेशा एक फ़ंक्शन घोषणा (या अमान्य) है। प्रश्न में कोड सी। में मान्य नहीं है
जोनाथन लेफ़लर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.