2015-11-04 5 views
9

मैंने कुछ कोड S s; लिखा ... s = {};, यह S s = {}; के समान होने की उम्मीद है। हालांकि यह नहीं था।ओवरलोड रिज़ॉल्यूशन: खाली ब्रेसिज़ का असाइनमेंट

#include <iostream> 

struct S 
{ 
    S(): a(5) { } 
    S(int t): a(t) {} 

    S &operator=(int t) { a = t; return *this; } 
    S &operator=(S const &t) = default; 

    int a; 
}; 

int main() 
{ 
    S s = {}; 

    S t; 
    t = {}; 

    std::cout << s.a << '\n'; 
    std::cout << t.a << '\n'; 
} 

उत्पादन होता है:

5 
0 

मेरे प्रश्न हैं:

  1. क्यों बदले "अस्पष्ट", operator=(int) यहाँ चयनित है या अन्य एक निम्न उदाहरण समस्या reproduces ?
  2. क्या S को बदले बिना कोई साफ कामकाज है?

मेरा इरादा s = S{}; है। s = {}; लिखना सुविधाजनक होगा अगर यह काम करता है। मैं वर्तमान में s = decltype(s){}; का उपयोग कर रहा हूं हालांकि मैं प्रकार या चर नाम को दोहराने से बचाना पसंद करूंगा।

+0

'{}' से 'int' पहचान रूपांतरण है ([\ [over.ics.list \]/9] (http://eel.is/c++draft/over.ics.list#9))। '{}' से 'एस' उपयोगकर्ता द्वारा परिभाषित रूपांतरण है ([\ [over.ics.list \]/6] (http://eel.is/c++draft/over.ics.list#6))। मैं कसम खाता हूं कि मैंने कल एक बहुत ही समान प्रश्न देखा ... –

+0

@ टी.सी. यदि हां, तो मुझे लगता है कि कल मैं और सवाल पढ़कर खुद को कुछ विकास समय बचा सकता था! –

+0

मुझे लगता है कि मेरे कोड में कई जगहें एक ही गलती हुई हैं ... उदा। मैं आमतौर पर 'शून्य स्पष्ट() {* यह = {} का उपयोग करता हूं; } 'किसी ऑब्जेक्ट को अपने मूल्य-प्रारंभिक स्थिति –

उत्तर

8

क्यों operator=(int) यहाँ चयन किया जाता है: यहाँ प्रासंगिक जानकारी है?

int को {} पहचान रूपांतरण ([over.ics.list]/9) है।{} से S उपयोगकर्ता द्वारा परिभाषित रूपांतरण ([over.ics.list]/6) है (तकनीकी रूप से, यह {} से const S& है, और [over.ics.list]/8 और [over.ics.ref] से पहले [over.ics] पर वापस आने से पहले चला जाता है। सूची]/6)।

पहली जीत।

क्या कोई साफ कामकाज है?

चाल std::experimental::optional के एक बदलाव t = {} हमेशा t खाली कर बनाने के लिए खींचती है। कुंजी operator=(int) एक टेम्पलेट बनाने के लिए है। आप int और केवल int स्वीकार करना चाहते हैं, तो यह

template<class Int, std::enable_if_t<std::is_same<Int, int>{}, int> = 0> 
S& operator=(Int t) { a = t; return *this; } 

विभिन्न बाधाओं यदि आप रूपांतरण (आप शायद यह भी कहा कि मामले में संदर्भ द्वारा तर्क ले जाना चाहते हैं) को सक्षम करना चाहते इस्तेमाल किया जा सकता हो जाता है।

बिंदु यह है कि सही ऑपरेंड के प्रकार को एक टेम्पलेट पैरामीटर बनाकर, आप t = {} को इस अधिभार का उपयोग करने से रोकते हैं - क्योंकि {} एक गैर-कटौती संदर्भ है।

... S को बदले बिना?

template<class T> T default_constructed_instance_of(const T&) { return {}; } और फिर s = default_constructed_instance_of(s); गिनती है?

+0

हे है, आखिरी पंक्ति के बारे में जो अब मैं' टेम्पलेट शून्य रीसेट (टी एंड टी) {टी = टी {}; } ' –

-1

सबसे पहले, मामले में असाइनमेंट ऑपरेटर के "int" संस्करण से कोई लेना देना नहीं है, आप इसे हटा सकते हैं। आप वास्तव में अन्य असाइनमेंट ऑपरेटर को भी हटा सकते हैं क्योंकि यह संकलक द्वारा उत्पन्न किया जाएगा। आईई इस तरह के प्रकार को स्वचालित रूप से प्रतिलिपि/चालक कन्स्ट्रक्टर और असाइनमेंट ऑपरेटर प्राप्त करता है। (यानी वे निषिद्ध और नहीं कर रहे हैं तो आप सिर्फ दोहरा रहे हैं जो संकलक स्पष्ट अंकन के साथ स्वचालित रूप से करता है)

पहला मामला

का उपयोग करता प्रतिलिपि प्रारंभ:

S s = {};  // the default constructor is invoked 

एक पोस्ट है कि -निर्माण निर्देश असाइनमेंट, अभी तक कंपाइलर ऐसे साधारण मामलों को अनुकूलित करते हैं। आप दिशा प्रारंभ बजाय का उपयोग करना चाहिए:

S s{};  // the default constructor is invoked (as you have it) 

ध्यान दें, आप भी लिख सकते हैं:

S s;   // the default constructor is invoked if you have it 

दूसरे मामले

आप क्या लिखना चाहिए की प्रत्यक्ष प्रारंभ है कॉपी असाइनमेंट का दायां हाथ:

t = S{}; 

यह नोटेशन डिफ़ॉल्ट कन्स्ट्रक्टर (यदि कोई है) का आह्वान करेगा, या सदस्यों के लिए मूल्य प्रारंभिक (जब तक कि एक प्रकार कुल है)। "अस्पष्ट" या अन्य एक के बजाय, http://en.cppreference.com/w/cpp/language/value_initialization

+0

मुझे अभी भी पता नहीं है कि उसका दूसरा मामला क्या कर रहा है (लिखित के रूप में) – pm100

+1

यदि मैं असाइनमेंट ऑपरेटर के "int" संस्करण को हटा देता हूं, तो आउटपुट '5 5' –

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