2016-07-06 5 views
7

मेरे पास एक अनिश्चित कक्षा है। इसे कॉपी करना समस्याग्रस्त होगा। मैं गारंटी है कि यह कभी कॉपी नहीं किया जाएगा करना चाहते हैं, तो मैं इसके प्रति निर्माता deleted बनाया:कॉपी एलिजन को कैसे कार्यान्वित करें, यह हटाए गए प्रतिलिपि निर्माता के साथ क्यों काम नहीं करेगा?

class A { 
    public: 
    A(); 
    A(const A&) = delete; 
}; 

A fun() { 
    return A(); 
}; 

int main() { 
    A a = fun(); 
}; 

दुर्भाग्य से, जी ++ कारण यह संकलन नहीं होगा:

t.cc: In function ‘A fun()’: 
t.cc:8:12: error: use of deleted function ‘A::A(const A&)’ 
    return A(); 
      ^
t.cc:4:5: note: declared here 
    A(const A&) = delete; 
    ^
t.cc: In function ‘int main()’: 
t.cc:12:13: error: use of deleted function ‘A::A(const A&)’ 
    A a = fun(); 
      ^
t.cc:4:5: note: declared here 
    A(const A&) = delete; 
    ^

लेकिन यह एक बहुत ही स्पष्ट स्थिति है जहां कॉपी एलिशन का उपयोग किया जाना चाहिए, इसलिए कॉपी कन्स्ट्रक्टर को कभी भी नहीं बुलाया जाना चाहिए। ऐसा क्यों है?

+1

प्रतीक्षा जब तक सी ++ 17, शायद यह –

+0

ओह गारंटी दी जाएगी। जवाब देने के लिए प्रेरित किया। –

+1

जेस्पर आपके उत्तर को दोहरा नहीं रहा है, आपने आगामी टिप्पणियों का उल्लेख नहीं किया है जब तक कि हमारी टिप्पणियां –

उत्तर

9

जब तक सी ++ 17 प्रति एलिशन एक अनुकूलन नहीं है, तो संकलक को करने की आवश्यकता नहीं है, इसलिए कक्षाएं कॉपी करने योग्य हो सकती हैं क्योंकि संकलक प्रतिलिपि बनाना चाहता है (भले ही यह वास्तव में नहीं है)। कई मामलों में सी ++ 17 प्रतिलिपि elision की गारंटी दी जाएगी और फिर कक्षाओं को प्रतिलिपि ctors की आवश्यकता नहीं होगी।

यह भी देखें:

http://en.cppreference.com/w/cpp/language/copy_elision

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0135r0.html

https://herbsutter.com/2016/06/30/trip-report-summer-iso-c-standards-meeting-oulu/

(के बारे में "गारंटी प्रतिलिपि इलिजन" बिट) आप शायद में प्रति निर्माता की घोषणा की पुरानी चाल इस्तेमाल कर सकते हैं आपकी कक्षा लेकिन वास्तव में इसे लागू नहीं करते? उस समय तक संकलक को खुश करना चाहिए जब तक यह वास्तव में प्रतिलिपि ctor का आह्वान नहीं करता है। मैंने इसका परीक्षण नहीं किया, लेकिन मेरा मानना ​​है कि इसे आपके मामले के लिए काम करना चाहिए जब तक कि सी ++ 17 न आए।

8

आप प्रतिलिपि इलिजन बाध्य नहीं कर सकता (अभी तक) (अन्य उत्तर देखें)।

लेकिन, आप अपने वर्ग के लिए एक डिफ़ॉल्ट चाल निर्माता प्रदान कर सकते हैं, इस पर आ जाएगा (और इस प्रकार, कॉपी नहीं) वापसी मान यदि RVO/NRVO संभव नहीं है। ऐसा करने के लिए आप अपनी चाल निर्माताओं के लिए = default जोड़ना चाहिए:

class A { 
    public: 
    A() = default; 
    A(const A&) = delete; 
    A(A&&) = default; 
    A& operator=(A&&) = default; 
}; 

Example

+0

मैं नीचे समझ नहीं सकता, विशेष रूप से स्पष्टीकरण के बिना। – peterh

+1

@peterh शायद क्योंकि यह आपके द्वारा पूछे गए प्रश्न का उत्तर नहीं दे रहा है। – juanchopanza

+0

ठीक है, लेकिन चालक कन्स्ट्रक्टरों की आवश्यकता क्यों है? एकमात्र रचनाकार जिसे इस उदाहरण में बुलाया जाना आवश्यक है, खाली कन्स्ट्रक्टर है। वास्तव में कोई चलती नहीं है। – peterh

7

वापसी मान अनुकूलन (RVO और NRVO) की आवश्यकता है कि प्रकार copyable या जंगम द्वारा शामिल गिरा दिया जाता है मतलब यह नहीं है। यह आवश्यकता लागू होती है, भले ही आपको आरवीओ मिल जाए या नहीं।

सबसे अधिक संभावना कारण यह इतना है कि प्रति इलिजन नहीं (वर्तमान में) लागू की जाती है है। यह एक अनुकूलन कि जगह ले सकता है, और यह कोई मतलब नहीं होगा कोड है कि अनुकूलन के लिए एक विशेष कार्यान्वयन में लागू किया जाता है कि क्या के आधार पर संकलित करने या नहीं करने के लिए।

सी ++ 17 में, RVO कुछ परिस्थितियों में लागू किया जा wil, और copyability और जंगमता की आवश्यकताओं को गिरा दिया जाएगा।

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