कॉपी कंस्ट्रक्टर क्या है?
कॉपी कंस्ट्रक्टर एक कंस्ट्रक्टर है जो उसी क्लास के पहले से बने ऑब्जेक्ट से इनिशियलाइज़ करके एक ऑब्जेक्ट बनाता है। कॉपी कंस्ट्रक्टर का उपयोग निम्न के लिए किया जाता है:
- एक ऑब्जेक्ट को उसी टाइप के दूसरे ऑब्जेक्ट से इनिशियलाइज़ करना
- किसी फ़ंक्शन को आर्गुमेंट के रूप में पास करने के लिए ऑब्जेक्ट कॉपी करना
- किसी फ़ंक्शन से ऑब्जेक्ट वापस करने के लिए कॉपी करना
यदि किसी क्लास में कॉपी कंस्ट्रक्टर परिभाषित नहीं है, तो कंपाइलर स्वयं एक डिफाइन करता है (शैलो कॉपी)। यदि क्लास में पॉइंटर वेरिएबल्स हैं और कुछ डायनामिक मेमोरी आवंटन हैं, तो कॉपी कंस्ट्रक्टर होना आवश्यक है।
सामान्य रूप
ClassName(const ClassName &obj) {
// कंस्ट्रक्टर बॉडी
}
यहां, obj उस ऑब्जेक्ट का रेफरेंस है जिसका उपयोग दूसरे ऑब्जेक्ट को इनिशियलाइज़ करने के लिए किया जा रहा है।
उदाहरण: पॉइंटर मेंबर के साथ डीप कॉपी
#include <iostream>
using namespace std;
class Line {
public:
int getLength() const;
Line(int len); // सिंपल कंस्ट्रक्टर
Line(const Line &obj); // कॉपी कंस्ट्रक्टर
~Line(); // डिस्ट्रक्टर
private:
int *ptr;
};
// मेंबर फंक्शन डेफिनिशन्स
Line::Line(int len) {
cout << "Normal constructor allocating ptr" << endl;
ptr = new int;
*ptr = len;
}
Line::Line(const Line &obj) {
cout << "Copy constructor allocating ptr." << endl;
ptr = new int; // नई मेमोरी आवंटित करें
*ptr = *obj.ptr; // वैल्यू कॉपी करें (डीप कॉपी)
}
Line::~Line() {
cout << "Freeing memory!" << endl;
delete ptr;
}
int Line::getLength() const {
return *ptr;
}
void display(Line obj) { // वैल्यू द्वारा पास - कॉपी कंस्ट्रक्टर कॉल होता है
cout << "Length of line: " << obj.getLength() << endl;
}
int main() {
Line line(10);
display(line); // कॉपी कंस्ट्रक्टर यहां कॉल होता है
return 0;
}
आउटपुट
Normal constructor allocating ptr Copy constructor allocating ptr. Length of line: 10 Freeing memory! Freeing memory!
कॉपी कंस्ट्रक्टर कब कॉल होता है?
Line line1(10); // नॉर्मल कंस्ट्रक्टर Line line2 = line1; // कॉपी कंस्ट्रक्टर (इनिशियलाइज़ेशन) Line line3(line1); // कॉपी कंस्ट्रक्टर (डायरेक्ट इनिशियलाइज़ेशन) display(line1); // कॉपी कंस्ट्रक्टर (वैल्यू द्वारा पास) Line line4 = getLine(); // कॉपी कंस्ट्रक्टर (रिटर्न वैल्यू - कॉपी एलिजन के बिना)
दूसरे उदाहरण के साथ आउटपुट
Normal constructor allocating ptr Copy constructor allocating ptr. // line2 = line1 Copy constructor allocating ptr. // display(line1) Length of line: 10 Freeing memory! // display का पैरामीटर नष्ट Copy constructor allocating ptr. // display(line2) Length of line: 10 Freeing memory! // display का पैरामीटर नष्ट Freeing memory! // line2 नष्ट Freeing memory! // line1 नष्ट
शैलो कॉपी vs डीप कॉपी
| पहलू | शैलो कॉपी (डिफ़ॉल्ट) | डीप कॉपी (कस्टम) |
|---|---|---|
| पॉइंटर मेंबर्स | समान एड्रेस कॉपी करता है | नई मेमोरी आवंटित करता है, डेटा कॉपी करता है |
| डबल फ्री जोखिम | हां (दोनों डिस्ट्रक्टर समान मेमोरी फ्री करते हैं) | नहीं (प्रत्येक का अपना आवंटन) |
| स्वतंत्रता | ऑब्जेक्ट्स स्थिति साझा करते हैं | ऑब्जेक्ट्स स्वतंत्र हैं |
रूल ऑफ थ्री / फाइव / ज़ीरो
- रूल ऑफ थ्री: यदि आप डिस्ट्रक्टर, कॉपी कंस्ट्रक्टर, या कॉपी असाइनमेंट ऑपरेटर में से किसी को डिफाइन करते हैं, तो संभवतः आपको तीनों को डिफाइन करना चाहिए
- रूल ऑफ फाइव (C++11): मूव कंस्ट्रक्टर और मूव असाइनमेंट ऑपरेटर जोड़ें
- रूल ऑफ ज़ीरो: RAII टाइप्स (vector, string, smart pointers) का उपयोग करें ताकि आपको कोई भी न लिखना पड़े
कॉपी असाइनमेंट ऑपरेटर (कॉपी कंस्ट्रक्टर के साथ आवश्यक)
Line& Line::operator=(const Line& other) {
if (this != &other) { // सेल्फ-असाइनमेंट चेक
delete ptr; // पुरानी मेमोरी रिलीज़
ptr = new int; // नई आवंटित करें
*ptr = *other.ptr; // डेटा कॉपी
}
return *this;
}