2013-08-17 6 views
54

इसक्या सदस्य-वार चालक कन्स्ट्रक्टर के बराबर `= डिफ़ॉल्ट 'चालक कन्स्ट्रक्टर है?

struct Example { 
    int a, b; 
    Example(int mA, int mB) : a{mA}, b{mB}    { } 
    Example(const Example& mE) : a{mE.a}, b{mE.b}  { } 
    Example(Example&& mE) : a{move(mE.a)}, b{move(mE.b)} { } 
    Example& operator=(const Example& mE) { a = mE.a; b = mE.b; return *this; } 
    Example& operator=(Example&& mE)  { a = move(mE.a); b = move(mE.b); return *this; } 
} 

इस

struct Example { 
    int a, b; 
    Example(int mA, int mB) : a{mA}, b{mB} { } 
    Example(const Example& mE)   = default; 
    Example(Example&& mE)     = default; 
    Example& operator=(const Example& mE) = default; 
    Example& operator=(Example&& mE)  = default; 
} 

के बराबर है?

+0

यह http://stackoverflow.com/questions/4819936/why-no-default-move-assignment-move-constructor –

+3

@ डाइटर लुकिंग का एक डुप्लिकेशंस हो सकता है: यह स्पष्ट रूप से नहीं है, हालांकि यह एक समान विषय पर है और कुछ उत्तर समान जमीन को कवर कर सकते हैं। हालांकि, हम एक दूसरे के डुप्लिकेट के रूप में चाल semantics के बारे में हर एक सवाल बंद नहीं करेंगे। –

+0

नोट, मैंने इस प्रश्न का मेरा जवाब जोड़ा क्योंकि उस समय मैं मानक से उद्धरण की तलाश कर रहा था जो साबित हुआ कि वे बराबर थे और स्वीकृत उत्तर ऐसा नहीं करता है। तो, मुझे अभी उद्धरण मिला और मेरा जवाब जोड़ा। –

उत्तर

27

हाँ दोनों एक जैसे हैं।

लेकिन

struct Example { 
    int a, b; 
    Example(int mA, int mB) : a{mA}, b{mB} { } 
    Example(const Example& mE)   = default; 
    Example(Example&& mE)     = default; 
    Example& operator=(const Example& mE) = default; 
    Example& operator=(Example&& mE)  = default; 
} 

इस संस्करण परमिट आप शरीर परिभाषा को छोड़ने के लिए होगा।

8.4.2 स्पष्ट रूप-डिफॉल्ट कार्यों [dcl.fct.def.default]

एक के समारोह परिभाषा:

हालांकि, अगर आप कुछ नियमों का पालन करने के लिए जब आप explicitly-defaulted-functions घोषित किया है प्रपत्र:

attribute-specifier-seqopt decl-specifier-seqopt declarator virt-specifier-seqopt = default ; 

एक स्पष्ट रूप-डिफॉल्ट परिभाषा कहा जाता है। एक समारोह है कि स्पष्ट रूप से चूक जाता है

  • एक विशेष सदस्य समारोह होगा,

  • ही घोषित समारोह प्रकार (संभवतः एक प्रति के मामले में रेफरी-क्वालिफायर और सिवाय इसके कि भिन्न के अलावा है निर्माता या कॉपी असाइनमेंट ऑपरेटर, पैरामीटर प्रकार, जहां T सदस्य समारोह के क्लास का नाम है) के रूप में अगर यह परोक्ष घोषित कर दिया गया था "गैर स्थिरांक T के संदर्भ में", हो सकता है

  • डिफ़ॉल्ट तर्क नहीं है।

+0

आप किस दस्तावेज़ से 8.4.2 उद्धृत कर रहे हैं? 8.4.2/1 में सी ++ 11 मानक या N36 9 0 में टेक्स्ट ", और * अपवाद-विनिर्देश * नहीं है"। वे दोनों 8.4.2/2 में कहते हैं: "एक स्पष्ट रूप से डिफॉल्ट फ़ंक्शन को केवल 'constexpr' घोषित किया जा सकता है अगर इसे स्पष्ट रूप से' कॉन्टेक्सप्र 'के रूप में घोषित किया गया हो, और हो सकता है कि यह एक स्पष्ट * अपवाद-विनिर्देश * हो, केवल तभी संगत (15.4) * अपवाद-विनिर्देश * के साथ निहित घोषणा पर। " – Casey

+1

@ कैसी अच्छा पकड़ो! मैं एन 3242 उद्धृत कर रहा था ... मैंने अपने दस्तावेज़ों को मिश्रित किया ... मैंने एन 36 9 0 को उद्धृत करने के लिए अपनी पोस्ट अपडेट की! इस बारे में बताने के लिए शुक्रिया ! –

+1

यदि मैं एक चालक और असाइनमेंट ऑपरेटर को '= डिफ़ॉल्ट' पर सेट करता हूं, तो क्या मैं ऑब्जेक्ट के साथ स्वैप कर पाऊंगा? क्या मुझे कन्स्ट्रक्टर को 'अस्वीकरण' के रूप में घोषित करने की आवश्यकता नहीं है? मैंने दोनों के लिए 'noexcept' और' = default' दोनों डालने का प्रयास किया, लेकिन यह संकलित नहीं होगा। – VF1

0

बहुत रोगजनक मामलों के अलावा ... हाँ।

अधिक सटीक होने के लिए, आपको सटीक नियमों के साथ अंतिम आधार Example भी माना जा सकता है। सबसे पहले आधार - घोषणा घोषणा - फिर सदस्यों, हमेशा घोषणा आदेश में।

14

हाँ, एक डिफॉल्ट की चाल निर्माता इसके आधार और सदस्यों के एक सदस्य के लिहाज से कदम है, तो प्रदर्शन करेंगे:

Example(Example&& mE)     = default; 

हम कर सकते हैं:

Example(Example&& mE) : a{move(mE.a)}, b{move(mE.b)} { } 

के बराबर है इसे draft C++11 standard अनुभाग 12.8पर जाकर देखें, कक्षा वस्तुओं की प्रतिलिपि बनाना और स्थानांतरित करना पराग्रा पीएच जो कहते हैं (जोर मेरा आगे जा रहा):

एक प्रति/स्थानांतरित निर्माता है कि चूक और नहीं परिभाषित किया गया है के रूप में नष्ट परोक्ष परिभाषित किया गया है अगर यह odrused है (3.2) या जब यह इसकी पहली घोषणा के बाद स्पष्ट रूप से डिफॉल्ट किया गया है। [नोट: प्रतिलिपि/चाल कन्स्ट्रक्टर को निश्चित रूप से परिभाषित किया गया है भले ही कार्यान्वयन इसके ओडीआर-उपयोग (3.2, 12.2) को बढ़ाया गया हो। अंत टिप्पणी] [...]

और पैरा कहते हैं जो:

एक गैर संघ दसवीं कक्षा के लिए परोक्ष परिभाषित कॉपी/कदम निर्माता एक प्रदर्शन सदस्य की प्रतिलिपि/इसके आधार और सदस्यों की चाल। [नोट: गैर स्थैतिक डेटा सदस्यों के ब्रेस-या-बराबर-प्रारंभकर्ताओं को अनदेखा किया जाता है। 12.6.2 में भी उदाहरण देखें। -जेंड नोट] प्रारंभिक क्रम का आधार बेस के प्रारंभिकरण और उपयोगकर्ता द्वारा परिभाषित कन्स्ट्रक्टर में सदस्यों के क्रम के समान है (12.6.2 देखें)। एक्स को या तो कन्स्ट्रक्टर के पैरामीटर या, चालक के लिए, पैरामीटर का संदर्भ देने वाला xvalue होने दें। प्रत्येक आधार या गैर स्थिर डेटा सदस्य नकल की जाती है/तरीके अपने प्रकार के लिए उपयुक्त में ले जाया गया:

  • यदि सदस्य एक सरणी है, प्रत्येक तत्व सीधे-प्रारंभ एक्स की इसी subobject साथ है;
  • यदि कोई सदस्य एम में Rvalue संदर्भ प्रकार T & & है, तो यह static_cast (x.m) के साथ प्रत्यक्ष-प्रारंभ होता है;
  • अन्यथा, आधार या सदस्य प्रत्यक्ष आधार या एक्स के सदस्य के साथ प्रत्यक्ष-प्रारंभिक है।

वर्चुअल बेस क्लास सबोबजेक्ट्स केवल द्वारा स्पष्ट रूप से परिभाषित प्रतिलिपि/चालक कन्स्ट्रक्टर (12.6.2 देखें) द्वारा शुरू किया जाएगा।

0

इस

को यह बराबर है हां। लेकिन यह केवल उन वर्गों के लिए मान्य है जिनके पास गैर-चलने योग्य सदस्य नहीं हैं।इस उदाहरण को देखो:

#include <iostream> 

struct nonmovable 
{ 
    nonmovable() = default; 

    nonmovable(const nonmovable &) = default; 
    nonmovable(  nonmovable &&) = delete; 
}; 

struct movable 
{ 
    movable() = default; 

    movable(const movable &) { std::cerr << "copy" << std::endl; } 
    movable(  movable &&) { std::cerr << "move" << std::endl; } 
}; 

struct has_nonmovable 
{ 
    movable a; 
    nonmovable b; 

    has_nonmovable() = default; 

    has_nonmovable(const has_nonmovable &) = default; 
    has_nonmovable(  has_nonmovable &&) = default; 
}; 

int main() 
{ 
    has_nonmovable c; 
    has_nonmovable d(std::move(c)); // prints copy 
} 

यह प्रिंट:

copy 

http://coliru.stacked-crooked.com/a/62c0a0aaec15b0eb

तो अगर एक वर्ग एक भी गैर जंगम सदस्य है, स्पष्ट रूप से चूक चाल निर्माता प्रतिलिपि कंस्ट्रक्टर्स का उपयोग करेगा सभी सदस्यों के लिए, यहां तक ​​कि जिनके पास चालक कन्स्ट्रक्टर है।

लेकिन सदस्यों को स्पष्ट रूप से परिभाषित या स्पष्ट रूप से डिफॉल्ट कन्स्ट्रक्टरों को डिफॉल्ट करने की आवश्यकता नहीं है। यदि चालक कन्स्ट्रक्टर को बिल्कुल घोषित नहीं किया जाता है, तो चालक का उपयोग उन सदस्यों के लिए किया जाएगा जिनके पास चालक कन्स्ट्रक्टर है और कॉपी कन्स्ट्रक्टर का उपयोग उन सदस्यों के लिए किया जाएगा जो चालक कन्स्ट्रक्टर को परिभाषित नहीं करते हैं। उदाहरण देखें:

#include <iostream> 

struct nonmovable 
{ 
    nonmovable() = default; 

    nonmovable(const nonmovable &) { std::cerr << "nonmovable::copy" << std::endl; } 
    //nonmovable(  nonmovable &&) = delete; 
}; 

struct movable 
{ 
    movable() = default; 

    movable(const movable &) { std::cerr << "movable::copy" << std::endl; } 
    movable(  movable &&) { std::cerr << "movable::move" << std::endl; } 
}; 

struct has_nonmovable 
{ 
    movable a; 
    nonmovable b; 

    has_nonmovable() = default; 

    has_nonmovable(const has_nonmovable &) = default; 
    has_nonmovable(  has_nonmovable &&) = default; 
}; 

int main() 
{ 
    has_nonmovable c; 
    has_nonmovable d(std::move(c)); 
} 

यह प्रिंट:

movable::move 
nonmovable::copy 

http://coliru.stacked-crooked.com/a/fda51f29a4b92881

क्लासेस चल लेकिन गैर copyable (जैसे unique_ptr) कर रहे हैं कर रहे हैं। ऐसे वर्ग हैं जो प्रतिलिपि बनाने योग्य हैं और प्रतिलिपि बनाने के लिए कॉपी कन्स्ट्रक्टर का उपयोग करते हैं। लेकिन मुझे एक वर्ग बनाने की कोई वजह नहीं है जो कॉपी करने योग्य है लेकिन स्पष्ट रूप से हटाए गए कन्स्ट्रक्टर को हटा दिया गया है।

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

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