2015-11-02 30 views
5

मान लीजिए मैं:ऑटो ए = ए (3) और ए ए (3) के बीच क्या अंतर है?

struct A 
{ 
    A(int x) : m_x(x) { } 
    A(A&&) = delete; 
    int m_x; 
} 

और:

A a(3); // Ok 
auto a = A(3); // Error: function A(int&&) cannot be referenced - it's a deleted function 

क्यों कदम निर्माता के बाद कॉल? जेनरेट कोड के मामले में ये 2 कथन अलग क्यों हैं?

उत्तर

4

आप दोनों कोड पथ समान होने की अपेक्षा क्यों करेंगे?

आप स्पष्ट रूप से दूसरे उदाहरण में एक अनाम वस्तु का निर्माण कर रहे हैं, आवंटन a (auto a) और फिर a के लिए अस्थायी से कॉपी (जो एक कदम है क्योंकि हम एक अस्थायी वस्तु के बारे में बात कर रहे हैं)।

+0

आपकी पहली टिप्पणी के बारे में, मेरी धारणा यह है कि इसे अक्सर "ये वही होते हैं, जो तकनीकी रूप से नहीं आते हैं, आमतौर पर नहीं आते हैं"। लेकिन शायद मैं ओपी के मुंह में शब्दों डाल रहा हूँ। – Hurkyl

+1

जो कोई उन्हें इस तरह पेश करता है उसे अक्षमता के लिए निकाल दिया जाना चाहिए। – Blindy

+0

जब इरादा स्पष्ट रूप से समान होता है तो संकलक अलग कोड क्यों उत्पन्न करेगा? क्या कोई ऐसा मामला है जहां प्रोग्रामर उस व्यवहार को चाहेगा? – Shmoopy

-1

इससे कोई फर्क नहीं पड़ता कि संकलक दोनों मामलों में एक ही कोड उत्पन्न करेगा, क्योंकि संकलित समय पर आवश्यक कार्यों/रचनाकारों को परिभाषित करने की आवश्यकता है। इस बारे में सोचें - अनुकूलन/कोड-पार्सिंग के बाद अनुकूलन होगा, लेकिन अंत में कोड इस मामले में समान होगा (होना चाहिए)।

+0

कोड को उसी मशीन कोड * में संकलित किया जाएगा * * – CoffeeandCode

6

auto a = A(3); का मतलब A a = A(3); जैसा है दाएं हाथ के प्रकार A है।

इसका मतलब यह है कि यह वास्तव में क्या दिखाई देता है: A(3) एक अस्थायी A3 साथ प्रारंभ बनाता है, और फिर A a = _____ का अर्थ है: बनाने के एक A_____ प्रारंभकर्ता के रूप में साथ a कहा जाता है।

तो आप एक अस्थायी बनाते हैं, a को प्रारंभकर्ता के रूप में पास करते हैं, और फिर अस्थायी नष्ट हो जाता है। इस प्रकार के प्रारंभिकरण (= के साथ) प्रति-प्रारंभिक कहा जाता है (हालांकि इसे "प्रतिलिपि" के साथ भ्रमित न करें, यह केवल एक शब्द है)।

a बनाने के लिए एक निर्माता का चयन किया गया है जो A स्वीकार करता है। यह या तो एक प्रति या एक चालक कन्स्ट्रक्टर होना चाहिए। A में एक चालक कन्स्ट्रक्टर और एक कॉपी कन्स्ट्रक्टर है। उत्तरार्द्ध पूरी तरह से उत्पन्न और परिभाषित के रूप में परिभाषित किया गया है, क्योंकि उपयोगकर्ता द्वारा घोषित चालक कन्स्ट्रक्टर है।

हटाए गए रूप में परिभाषित होने पर ओवरलोड रिज़ॉल्यूशन को प्रभावित नहीं किया जाता है; और इस मामले में प्रति-निर्माता को प्रति-निर्माता को प्राथमिकता दी जाती है।

तो आपका कोड delete डी फ़ंक्शन को कॉल करने का प्रयास करता है, जो खराब है, इसलिए त्रुटि है।

ध्यान दें कि यदि चालक-निर्माता को हटाया नहीं गया था, तो प्रतिलिपि प्रतिलिपि लागू होगी। यह कुछ परिस्थितियों में चलता है जहां एक चर को अस्थायी से प्रारंभ किया जाता है, या स्थानीय चर वैल्यू द्वारा वापस किया जाता है। नियम यह है कि संकलक a और अस्थायी वस्तु दोनों के लिए एक ही स्मृति का उपयोग कर सकता है, और प्रतिलिपि/चालक कन्स्ट्रक्टर को कॉल छोड़ दें।

अधिकांश/सभी कंपाइलर्स वास्तव में परिस्थिति में ऐसा करेंगे। तो आप वास्तव में auto a = A(3); लिख सकते हैं और अभ्यास में कोई अनावश्यक चाल नहीं प्राप्त कर सकते हैं। यदि आप अपने चालक-निर्माता के लिए कुछ कोड लिखते हैं जो कुछ आउटपुट करता है, तो आप उम्मीद करेंगे कि कुछ भी आउटपुट नहीं है।

यदि आप पूरी तरह से सुनिश्चित करना चाहते हैं कि कोई अनावश्यक प्रतिलिपि नहीं है, या ऐसी वस्तु का निर्माण करें जिसमें कोई उपयोग करने योग्य प्रति न हो और न ही कन्स्ट्रक्टर को स्थानांतरित करें - लिखने वाले कोड को रोकें जो अनावश्यक प्रतियां निर्दिष्ट करता है! A a(3); पर्याप्त है।

+0

पर ऑप्टिमाइज़ेशन के साथ, मुझे आश्चर्य है कि क्या इस कंपाइलर को इस मामले में इस कदम को बढ़ाने की अनुमति है, जहां कन्स्ट्रक्टर को हटाया जाता है? – Mikhail

+0

@ मिखाइल क्षमा करें, प्रश्न को गलत तरीके से पढ़ें। मेरा जवाब अपडेट करेगा –

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