असाइनमेंट में 2 चरण होते हैं: एक ऑब्जेक्ट की पुरानी स्थिति को तोड़ना और उसके लिए एक नई स्थिति बनाना। डिस्ट्रक्टर पहले चरण के लिए उपयोग किया जाता है और कॉपी कंस्ट्रक्टर दूसरे चरण के लिए।
इन दोनों को लागू करना सीधा है। लेकिन जब असाइनमेंट ऑपरेटर को ओवरलोड करते हैं, तो इसे लागू करना काफी मुश्किल हो सकता है। कॉपी-एंड-स्वैप इडियम इसका समाधान है।
यह इडियम डेटा की एक स्थानीय कॉपी बनाने के लिए कॉपी कंस्ट्रक्टर का उपयोग करता है। फिर यह स्वैप फ़ंक्शन का उपयोग करके पुराने डेटा को नए डेटा के साथ स्वैप करता है। अस्थायी कॉपी को फिर डिस्ट्रक्टर का उपयोग करके नष्ट कर दिया जाता है। अंत में हमारे पास केवल नए डेटा की एक कॉपी होती है।
तो, कॉपी-एंड-स्वैप इडियम को तीन चीजों की आवश्यकता होती है:
- कॉपी कंस्ट्रक्टर
- डिस्ट्रक्टर
- स्वैप फ़ंक्शन
एक स्वैप फ़ंक्शन एक नॉन-थ्रोइंग फ़ंक्शन है जो एक क्लास के दो ऑब्जेक्ट्स को स्वैप करता है, मेंबर दर मेंबर।
नोट: आपको
std::swapफ़ंक्शन का उपयोग नहीं करना चाहिए क्योंकि यह आंतरिक रूप से कॉपी कंस्ट्रक्टर और असाइनमेंट ऑपरेटर का उपयोग करके वही प्राप्त करता है।
क्लासिक कार्यान्वयन
class MyClass {
int* data;
size_t size;
public:
// कॉपी कंस्ट्रक्टर
MyClass(const MyClass& other) : data(new int[other.size]), size(other.size) {
copy(other.data, other.data + size, data);
}
// डिस्ट्रक्टर
~MyClass() { delete[] data; }
// स्वैप फ़ंक्शन (नॉन-थ्रोइंग)
void swap(MyClass& other) noexcept {
std::swap(data, other.data);
std::swap(size, other.size);
}
// असाइनमेंट ऑपरेटर - कॉपी-एंड-स्वैप इडियम
MyClass& operator=(MyClass other) { // पास-बाय-वैल्यू कॉपी बनाता है
swap(other); // पुराने डेटा को नए के साथ स्वैप करें
return *this; // other (पुराना डेटा) स्कोप से बाहर जाकर नष्ट हो जाता है
}
};
क्यों काम करता है?
MyClass other- पैरामीटर वैल्यू द्वारा पास होता है, इसलिए कॉपी कंस्ट्रक्टर कॉल होता है (नया डेटा बनाता है)swap(other)- वर्तमान ऑब्जेक्ट का डेटा नए डेटा के साथ स्वैप होता हैreturn *this-otherस्कोप से बाहर जाता है, इसका डिस्ट्रक्टर पुराना डेटा साफ करता है
लाभ
- एक्सेप्शन सेफ्टी: स्ट्रॉन्ग एक्सेप्शन गारंटी - यदि कॉपी फेल होती है, तो मूल ऑब्जेक्ट अपरिवर्तित रहता है
- सेल्फ-असाइनमेंट सुरक्षित:
a = aस्वचालित रूप से काम करता है - कोड डुप्लीकेशन नहीं: कॉपी कंस्ट्रक्टर और डिस्ट्रक्टर का पुनः उपयोग
- सरल और साफ: मैन्युअल मेमोरी प्रबंधन तर्क की आवश्यकता नहीं
C++11 मूव सेमांटिक्स के साथ
class MyClass {
// ... वही मेंबर्स ...
// मूव कंस्ट्रक्टर
MyClass(MyClass&& other) noexcept : data(other.data), size(other.size) {
other.data = nullptr;
other.size = 0;
}
// कॉपी असाइनमेंट (कॉपी-एंड-स्वैप)
MyClass& operator=(MyClass other) {
swap(other);
return *this;
}
// मूव असाइनमेंट (वैकल्पिक, ऑप्टिमाइज़ेशन के लिए)
MyClass& operator=(MyClass&& other) noexcept {
if (this != &other) {
delete[] data;
data = other.data;
size = other.size;
other.data = nullptr;
other.size = 0;
}
return *this;
}
};
मुख्य बिंदु
- पास-बाय-वैल्यू पैरामीटर कॉपी/मूव दोनों को हैंडल करता है
noexcept स्वैप के लिए महत्वपूर्ण है- कॉपी कंस्ट्रक्टर, डिस्ट्रक्टर, स्वैप - तीनों सही होने चाहिए