c++ वजन मानक पुस्तकालय std:: स्वैप कैसे कार्यान्वित करता है?




सार्वजनिक पुस्तकालय जयपुर राजस्थान (2)

एसटीएल में स्वैप समारोह कैसे लागू किया जाता है?

कौन सा कार्यान्वयन? यह एक विनिर्देश है, न कि एक ठोस पुस्तकालय। यदि आपका मतलब है कि मेरे कंपाइलर की मानक लाइब्रेरी यह कैसे करती है , तो हमें बताएं कि कौन सा कंपाइलर है, या कोड को स्वयं पढ़ें।

क्या यह उतना आसान है जितना:

यह अनिवार्य रूप से बेवकूफ संस्करण प्री-सी ++ 11 है।

यह अन-विशिष्ट कार्यान्वयन एक प्रतिलिपि T = std::vector<SomethingExpensive> आपके उदाहरण में T = std::vector<SomethingExpensive> लिए, कोड इस प्रकार अनुवाद करता है:

template<typename T> void swap(T& t1, T& t2) {
  T tmp(t1); // duplicate t1, making an expensive copy of each element
  t1=t2;     // discard the original contents of t1,
             // and replace them with an expensive duplicate of t2
  t2=tmp;    // discard the original contents of t2,
             // and replace them with an expensive duplicate of tmp
}            // implicitly destroy the expensive temporary copy of t1

इसलिए दो वैक्टरों का आदान-प्रदान करने के लिए हमने अनिवार्य रूप से तीन बनाया। तीन गतिशील आवंटन थे और बहुत सारी महंगी वस्तुओं की प्रतिलिपि बनाई गई थी, और इनमें से कोई भी ऑपरेशन फेंक सकता है, संभावित रूप से तर्क को अनिश्चित स्थिति में छोड़ सकता है।

चूंकि यह स्पष्ट रूप से भयानक था, महंगे कंटेनरों के लिए ओवरलोड प्रदान किए गए थे, और आपको अपने महंगे प्रकारों के लिए ओवरलोड लिखने के लिए प्रोत्साहित किया गया था: उदाहरण के लिए। std::vector विशेषज्ञता के पास वेक्टर के आंतरिक तक पहुंच थी, और सभी प्रतिलिपि के बिना दो वैक्टरों को स्वैप कर सकता था:

template <typename T> void swap(vector<T> &v1, vector<T> &v2) { v1.swap(v2); }
template <typename T> void vector<T>::swap(vector<T>& other) {
  swap(this->size_, other.size_); // cheap integer swap of allocated count
  swap(this->used_, other.used_); // cheap integer swap of used count
  swap(this->data__, other.data_); // cheap pointer swap of data ptr
}

ध्यान दें कि इसमें किसी भी महंगी, कोई गतिशील (डी) आवंटन पर कोई प्रतियां शामिल नहीं हैं, और इसकी गारंटी है कि फेंक न दें।

अब, इस विशेषज्ञता का कारण यह है कि वेक्टर :: स्वैप के पास वेक्टर के आंतरिक तक पहुंच है, और प्रतिलिपि के बिना सुरक्षित रूप से और कुशलतापूर्वक उन्हें स्थानांतरित कर सकते हैं।

मुझे ऐसा करने की ज़रूरत क्यों होगी [विशेषज्ञता ... अपनी कक्षा के लिए]?

प्री-सी ++ 11, उसी कारण से std::vector - स्वैपिंग कुशल और अपवाद-सुरक्षित बनाने के लिए।

सी ++ 11 के बाद से, आप वास्तव में नहीं करते हैं - यदि आप या तो निर्माण निर्माण और असाइनमेंट प्रदान करते हैं, या कंपाइलर आपके लिए साइन डिफ़ॉल्ट उत्पन्न कर सकता है।

नया जेनेरिक स्वैप:

template <typename T> void swap(T& t1, T& t2) {
    T temp = std::move(t1);
    t1 = std::move(t2);
    t2 = std::move(temp);
}

एक कस्टम कार्यान्वयन लिखने के बिना उपरोक्त कस्टम वेक्टर कार्यान्वयन के रूप में अनिवार्य रूप से वही व्यवहार प्राप्त करने के लिए चाल निर्माण / असाइनमेंट का उपयोग कर सकते हैं।

एसटीएल में स्वैप समारोह कैसे लागू किया जाता है? क्या यह उतना आसान है जितना:

template<typename T> void swap(T& t1, T& t2) {
    T tmp(t1);
    t1=t2;
    t2=tmp;
}

अन्य पदों में, वे इस कार्य को अपनी कक्षा के लिए विशेषज्ञता के बारे में बात करते हैं। मुझे ऐसा करने की ज़रूरत क्यों होगी? मैं std::swap फ़ंक्शन का उपयोग क्यों नहीं कर सकता?


std::swap कैसे कार्यान्वित किया जाता है?

हां, प्रश्न में प्रस्तुत कार्यान्वयन क्लासिक सी ++ 03 एक है।

std::swap एक और आधुनिक (सी ++ 11) कार्यान्वयन इस तरह दिखता है:

template<typename T> void swap(T& t1, T& t2) {
    T temp = std::move(t1); // or T temp(std::move(t1));
    t1 = std::move(t2);
    t2 = std::move(temp);
}

यह संसाधन प्रबंधन के संदर्भ में क्लासिक सी ++ 03 कार्यान्वयन में सुधार है क्योंकि यह अनियंत्रित प्रतियों को रोकता है, आदि। यह, सी ++ 11 std::swap , प्रकार T को MoveConstructible करने के लिए आवश्यक है MoveConstructible और MoveAssignable , इस प्रकार अनुमति देता है कार्यान्वयन और सुधार।

मुझे कस्टम कार्यान्वयन प्रदान करने की आवश्यकता क्यों होगी?

एक विशिष्ट प्रकार के लिए swap का एक कस्टम कार्यान्वयन आमतौर पर सलाह दी जाती है जब आपका कार्यान्वयन मानक संस्करण से अधिक कुशल या विशिष्ट होता है।

इसका एक उत्कृष्ट उदाहरण यह है कि जब आपकी कक्षा बड़ी मात्रा में संसाधनों का प्रबंधन करती है जो प्रतिलिपि बनाना और फिर हटा देना महंगा होगा। इसके बजाए, आपका कस्टम कार्यान्वयन स्वैप को प्रभावित करने के लिए आवश्यक हैंडल या पॉइंटर्स का आदान-प्रदान कर सकता है।

std::move और movable प्रकारों के आगमन के साथ (और आपके प्रकार को इस तरह कार्यान्वित किया गया है), लगभग सी ++ 11 और बाद में, यहां पर बहुत सारे मूल तर्कों को गिरना शुरू हो रहा है; लेकिन फिर भी, यदि एक कस्टम स्वैप मानक से बेहतर होगा, तो इसे लागू करें।

यदि सामान्य रूप से ADL तंत्र का उपयोग करता है तो जेनेरिक कोड आमतौर पर आपके कस्टम swap का उपयोग करने में सक्षम होगा।







swap