c++ - जब एसटीएल कंटेनर को खुद में कॉपी किया जाता है, तो क्या एसटीएल कंटेनर को तत्वों की नकल करने से बचना चाहिए?




stl language-lawyer (3)

सवाल स्व-असाइनमेंट के बारे में है। उदाहरण के लिए एक वेक्टर को स्वयं में कॉपी करना:

std::vector<std::string> vec(5, "hello");
vec = vec;

ऊपर दिए गए कोड को स्ट्रिंग्स के 5 असाइनमेंट ऑपरेशंस को खुद में करना चाहिए, या बस कुछ नहीं करना चाहिए? मेरा मतलब है कि निम्नलिखित जाँच मान्य है:

std::vector operator=(const std::vector &rhs)
{
    if (this == &rhs)
        { return *this; }
    ...
}

मैं अपने स्वयं के std::variant कार्यान्वयन पर काम कर रहा हूं std::variant क्लास (सिर्फ मनोरंजन के लिए) और दिलचस्पी है अगर मुझे असाइनमेंट ऑपरेटर की शुरुआत में एक स्व-असाइनमेंट चेक जोड़ना चाहिए, या क्या मुझे केवल निहित तत्व को खुद में कॉपी करना चाहिए?

मैं समझता हूं कि आम तौर पर यह कोई मायने नहीं रखता। आपको एक ऐसा वर्ग नहीं बनाना चाहिए जो स्वयं में नकल करने के तथ्य का उपयोग करता है। लेकिन मुझे दिलचस्पी है अगर मानक इस बारे में कुछ भी कहता है।


[...] अगर मुझे असाइनमेंट ऑपरेटर की शुरुआत में इस जाँच को जोड़ना चाहिए [...]?

आपको यह ध्यान रखना चाहिए कि क्या std::vector , या अन्य STL कंटेनर आपके लिए ऐसा करते हैं। एक उपयोगकर्ता की कल्पना करें जो आपके पुस्तकालय के साथ काम करता है और एसटीएल कंटेनरों के दायरे के बाहर x = x करता है।

अब एसटीएल कंटेनर आवश्यकताओं के लिए - मेरा मानना ​​है कि मानक निर्दिष्ट नहीं करता है कि क्या असाइनमेंट को एक स्व-असाइनमेंट होने के लिए चेक करने की आवश्यकता है ( Containers library अनुभाग के अधिकांश भाग के माध्यम से)। यह संकलक अनुकूलन के लिए जगह देता है और मेरा मानना ​​है कि एक सभ्य संकलक को इस तरह की जाँच करनी चाहिए।


दिलचस्पी है कि क्या मुझे असाइनमेंट ऑपरेटर की शुरुआत में एक स्व-असाइनमेंट चेक जोड़ना चाहिए, या क्या मुझे केवल निहित तत्व को ही कॉपी करना चाहिए?

C ++ कोर दिशानिर्देश किसी उपयोगकर्ता वर्ग में स्व-असाइनमेंट चेक नहीं करने की सलाह देते हैं यदि इसके सभी सदस्य स्व-असाइनमेंट हैं:

प्रवर्तन (सरल) असाइनमेंट ऑपरेटरों में पैटर्न शामिल नहीं होना चाहिए if (this == &a) return *this; ???

यह एक दक्षता के कारण है। स्व-कार्य व्यवहार में होने की संभावना नहीं है। वे दुर्लभ हैं, और इसलिए प्रत्येक ऑपरेशन में एक स्व-असाइनमेंट चेक करने से बचना बेहतर है। एक स्व-असाइनमेंट चेक संभवतः स्व-असाइनमेंट केस (बहुत दुर्लभ) में कोड को तेज करता है और इसे अन्य सभी मामलों (अधिक सामान्य) में धीमा बनाता है।

कल्पना कीजिए कि आप एक लाख तत्व असाइन करते हैं। प्रत्येक असाइनमेंट ऑपरेशन में एक स्व-असाइनमेंट चेक किया जाता है। और यह शायद सबसे अधिक है कि यह कुछ भी नहीं के लिए किया जाता है क्योंकि कोई भी असाइनमेंट वास्तव में एक स्व-असाइनमेंट नहीं है। और इसलिए हम एक लाख बेकार जाँच करते हैं।

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

हालाँकि, स्व-असाइनमेंट चेक अभी भी उन वर्गों के लिए उपयोग किया जाना चाहिए जो स्व-असाइनमेंट डिफ़ॉल्ट रूप से सुरक्षित नहीं हैं। उदाहरण std::vector । वेक्टर, जिसे पहले कॉपी किया जा रहा है, पहले मौजूदा तत्वों को हटाना होगा। लेकिन यदि गंतव्य वेक्टर और स्रोत वेक्टर एक ही वस्तु है, तो गंतव्य वेक्टर में तत्वों को हटाकर हम उन्हें स्रोत वेक्टर में भी हटा देते हैं। और इसलिए विलोपन के बाद उन्हें कॉपी करना संभव नहीं होगा। यही कारण है कि libstdc ++ , std::vector लिए एक स्व-असाइनमेंट चेक करता है (हालांकि यह std::vector को implement करना संभव है: std::vector असाइनमेंट चेक के बिना std::vector )।

लेकिन यह ऐसा नहीं करता है std::variant उदाहरण के लिए std::variant । यदि आप स्वयं में एक संस्करण की नकल करते हैं तो निहित मूल्य स्वयं में कॉपी हो जाएगा। coliru.stacked-crooked.com/a/095d633dd908d53e देखें। क्योंकि इसे अपने आप में कॉपी करना सेल्फ असाइनमेंट सेफ़ है (बशर्ते निहित मूल्य सेल्फ असाइनमेंट सुरक्षित हो)।

इस प्रकार, libstdc ++ std::vector लिए एक स्व-असाइनमेंट की जाँच करता है std::vector (सेल्फ-असाइनमेंट सुरक्षा प्रदान करने के लिए), और std::variant लिए नहीं std::variant (दक्षता के लिए)।


this == &rhs जाँच करना this == &rhs वास्तव में एक बहुत अच्छी तरह से ज्ञात मुहावरा है , और यह सुनिश्चित करने में मदद करता है कि आप इस बात की गारंटी नहीं देते हैं कि lhs और lhs भिन्न वस्तुएँ हैं। तो, यह वैध है और वास्तव में प्रोत्साहित किया गया है।

मैं नहीं जानता कि क्या एसटीएल कंटेनरों को चेक करना आवश्यक है, हालांकि।





c++-standard-library