2014-11-07 11 views
5

क्लैंग 3.5.0 और जीसीसी 4.9.1 के साथ निम्न कोड संकलित अंतिम विवरण में एक त्रुटि उत्पन्न करता है। जबकि bar({1, 2}) नहीं हैब्रांडेड-इनिट-लिस्ट एक कन्स्ट्रक्टर आमंत्रण बनाम फ़ंक्शन कॉल में अलग-अलग व्यवहार क्यों करती है?

#include <iostream> 

struct Foo { Foo(int x, int y) { std::cout << "Foo(int = " << x << ", int = " << y << ")" << std::endl; } }; 

void bar(int x, int y) { std::cout << "bar(int = " << x << ", int = " << y << ")" << std::endl; } 

int main() 
{ 
    Foo({}, {}); // Foo(int = 0, int = 0) 
    Foo({1}, {2}); // Foo(int = 1, int = 2) 
    Foo({1, 2}); // Foo(int = 1, int = 2) 

    bar({}, {}); // bar(int = 0, int = 0) 
    bar({1}, {2}); // bar(int = 1, int = 2) 
    bar({1, 2}); // error: no matching function for call to 'bar' <<< Why? <<< 
} 

क्यों Foo({1, 2}) ठीक है?

विशेष रूप से, तर्क के बारे में जानना बहुत अच्छा होगा।

+3

मेरा अनुमान है, 'फू ({1,2})' एक अस्थायी फू वस्तु बनाता है और प्रति ctor कॉल । – Borgleader

+0

@ बॉर्गलीडर धन्यवाद, यह समझ में आता है! :-) – precarious

+0

@ बोर्गलीडर द्वारा टिप्पणी सही है - {1, 2} के साथ आप एक अस्थायी फू ऑब्जेक्ट बना सकते हैं, लेकिन केवल जब फू की अपेक्षा की जाती है। आप वास्तव में इसके साथ काम करने के लिए एकाधिक पैरामीटर पारित नहीं कर सकते हैं। –

उत्तर

6

Foo({1,2}) एक अस्थायी Foo ऑब्जेक्ट बनाता है और कॉपी कन्स्ट्रक्टर को कॉल करता है।

प्रतिलिपि निर्माता के साथ इस संशोधित उदाहरण देखें हटाएँ: http://coliru.stacked-crooked.com/a/6cb80746a8479799

यह त्रुटियों के साथ:

main.cpp:6:5: note: candidate constructor has been explicitly deleted 
    Foo(const Foo& f) = delete; 
+0

लेकिन मूल उदाहरण में अंतर्निहित एक प्रतिलिपि निर्माता नहीं था? इसे क्यों हटाएं और संकलित न करने का एक अन्य कारण क्यों है? यह exaplain क्यों नहीं है क्यों 'बार' नहीं कहा जा सकता है; और यह बार के तर्कों के बारे में है, इसे देखें [संकलन को ठीक करने का तरीका] (http://coliru.stacked-crooked.com/a/2b8f6fee6244c251) –

+0

@NorahAttkins आप बिंदु चूक गए। मुद्दा यह था कि प्रारंभकर्ता सूची कन्स्ट्रक्टर को 2 इंट्स नहीं दे रही है (जिसे ओपी ने माना था, और सोच रहा था कि यह फ़ंक्शन कॉल में क्यों काम नहीं करेगा जो 2 इंच भी लेता है), यह एक अस्थायी वस्तु उत्पन्न कर रहा है और उसे कॉल कर रहा है प्रतिलिपि निर्माता। इसे हटाने से पता चला कि कॉपी कन्स्ट्रक्टर को बुलाया जा रहा था। – Borgleader

+0

नहीं, यह नहीं किया; इसे देखें [उदाहरण] (http://coliru.stacked-crooked.com/a/7314848093d2987a) अगर मैं 'Foo ({1, 2}) पर कॉल को हटा देता हूं, तो प्रोग्राम अभी भी' बार 'को कॉल करते समय संकलित करने में विफल रहता है कभी भी हटाए गए प्रतिलिपि बनाने वालों के बारे में कुछ भी उल्लेख करते हैं। 'बार' के कॉल ने कभी भी अस्थायी 'फू' ऑब्जेक्ट नहीं बनाया –

1

लाइन

bar({1, 2}); 

वास्तव में bar समारोह में गुजरता है, की एक अस्थायी वस्तु टाइप करें

<brace-enclosed initializer list> // it's made clear in the comments that brace initializers have no type 

और इस अस्थायी वस्तु को पहले तर्क के प्रकार में परिवर्तित करने का कोई तरीका नहीं है जो int है। इस प्रकार error

<brace-enclosed initializer list>int को तर्क 1 के लिए परिवर्तित नहीं कर सकते

void bar(int, int) 
+0

नहीं, यह सही नहीं है। एक ब्रेसिड-इनिट-लिस्ट में कोई प्रकार नहीं है। – Columbo

+0

@ कोल्मुबो क्या आप [निश्चित] हैं (http://coliru.stacked-crooked.com/a/7dbfd72283b52c55)? –

+1

@ नोराह एटकिन्स [एक ब्रेसिड प्रारंभकर्ता के पास कोई प्रकार नहीं है] (http://www.youtube.com/watch?v=wQxj20X-tIU&list=UUMlGfpWw-RUdWX_JbLCukXg#t=1792) – Borgleader

संबंधित मुद्दे