בנאי העתקה הוא עמוס יתר על המידה בנאי המשמש להכרזה ולאתחול של אובייקט מאובייקט אחר.
Copy Constructor הוא משני סוגים:
תחביר של בונה העתקות המוגדר על ידי המשתמש:
Class_name(const class_name &old_object);
שקול את המצב הבא:
שפה גרובי
class A { A(A &x) // copy constructor. { // copyconstructor. } }
במקרה הנ'ל, ניתן לקרוא לבנות העתקות בדרכים הבאות:
בואו נראה דוגמה פשוטה של בנאי ההעתקה.
// תוכנית של בנאי ההעתקה.
#include using namespace std; class A { public: int x; A(int a) // parameterized constructor. { x=a; } A(A &i) // copy constructor { x = i.x; } }; int main() { A a1(20); // Calling the parameterized constructor. A a2(a1); // Calling the copy constructor. cout< <a2.x; return 0; } < pre> <p> <strong>Output:</strong> </p> <pre> 20 </pre> <h2>When Copy Constructor is called</h2> <p>Copy Constructor is called in the following scenarios:</p> <ul> <li>When we initialize the object with another existing object of the same class type. For example, Student s1 = s2, where Student is the class.</li> <li>When the object of the same class type is passed by value as an argument.</li> <li>When the function returns the object of the same class type by value.</li> </ul> <h2>Two types of copies are produced by the constructor:</h2> <ul> <li>Shallow copy</li> <li>Deep copy</li> </ul> <h2>Shallow Copy</h2> <ul> <li>The default copy constructor can only produce the shallow copy.</li> <li>A Shallow copy is defined as the process of creating the copy of an object by copying data of all the member variables as it is.</li> </ul> <p>Let's understand this through a simple example:</p> <pre> #include using namespace std; class Demo { int a; int b; int *p; public: Demo() { p=new int; } void setdata(int x,int y,int z) { a=x; b=y; *p=z; } void showdata() { std::cout << 'value of a is : ' < <a<< std::endl; std::cout << 'value of b is : ' < <b<< *p <<*p<< } }; int main() { demo d1; d1.setdata(4,5,7); d2="d1;" d2.showdata(); return 0; pre> <p> <strong>Output:</strong> </p> <pre> value of a is : 4 value of b is : 5 value of *p is : 7 </pre> <img src="//techcodeview.com/img/c-tutorial/75/c-copy-constructor-3.webp" alt="C++ Copy Constructor"> <p>In the above case, a programmer has not defined any constructor, therefore, the statement <strong>Demo d2 = d1;</strong> calls the default constructor defined by the compiler. The default constructor creates the exact copy or shallow copy of the existing object. Thus, the pointer p of both the objects point to the same memory location. Therefore, when the memory of a field is freed, the memory of another field is also automatically freed as both the fields point to the same memory location. This problem is solved by the <strong>user-defined constructor</strong> that creates the <strong>Deep copy</strong> .</p> <h2>Deep copy</h2> <p>Deep copy dynamically allocates the memory for the copy and then copies the actual value, both the source and copy have distinct memory locations. In this way, both the source and copy are distinct and will not share the same memory location. Deep copy requires us to write the user-defined constructor.</p> <p>Let's understand this through a simple example.</p> <pre> #include using namespace std; class Demo { public: int a; int b; int *p; Demo() { p=new int; } Demo(Demo &d) { a = d.a; b = d.b; p = new int; *p = *(d.p); } void setdata(int x,int y,int z) { a=x; b=y; *p=z; } void showdata() { std::cout << 'value of a is : ' < <a<< std::endl; std::cout << 'value of b is : ' < <b<< *p <<*p<< } }; int main() { demo d1; d1.setdata(4,5,7); d2="d1;" d2.showdata(); return 0; pre> <p> <strong>Output:</strong> </p> <pre> value of a is : 4 value of b is : 5 value of *p is : 7 </pre> <img src="//techcodeview.com/img/c-tutorial/75/c-copy-constructor-4.webp" alt="C++ Copy Constructor"> <p>In the above case, a programmer has defined its own constructor, therefore the statement <strong>Demo d2 = d1;</strong> calls the copy constructor defined by the user. It creates the exact copy of the value types data and the object pointed by the pointer p. Deep copy does not create the copy of a reference type variable.</p> <h2>Differences b/w Copy constructor and Assignment operator(=)</h2> <table class="table"> <tr> <th>Copy Constructor</th> <th>Assignment Operator</th> </tr> <tr> <td>It is an overloaded constructor.</td> <td>It is a bitwise operator.</td> </tr> <tr> <td>It initializes the new object with the existing object.</td> <td>It assigns the value of one object to another object.</td> </tr> <tr> <td>Syntax of copy constructor: <br> Class_name(const class_name &object_name) <br> { <br> // body of the constructor. <br> }</td> <td>Syntax of Assignment operator: <br> Class_name a,b; <br> b = a;</td> </tr> <tr> <td><ul> <li>The <strong>copy constructor</strong> is invoked when the new object is initialized with the existing object.</li> <li>The object is passed as an argument to the function.</li> <li>It returns the object.</li> </ul></td> <td>The <strong>assignment operator</strong> is invoked when we assign the existing object to a new object.</td> </tr> <tr> <td>Both the existing object and new object shares the different memory locations.</td> <td>Both the existing object and new object shares the same memory location.</td> </tr> <tr> <td>If a programmer does not define the copy constructor, the compiler will automatically generate the implicit default copy constructor. </td> <td>If we do not overload the '=' operator, the bitwise copy will occur.</td> </tr> </table> <hr></a<<></pre></a<<></pre></a2.x;>
כאשר קוראים Copy Constructor
Copy Constructor נקרא בתרחישים הבאים:
- כאשר אנו מאתחלים את האובייקט עם אובייקט קיים אחר מאותו סוג מחלקה. לדוגמה, Student s1 = s2, כאשר Student הוא הכיתה.
- כאשר האובייקט מאותו סוג מחלקה מועבר על ידי ערך כארגומנט.
- כאשר הפונקציה מחזירה את האובייקט מאותו סוג מחלקה לפי ערך.
שני סוגים של עותקים מיוצרים על ידי הבנאי:
- עותק רדוד
- עותק עמוק
עותק רדוד
- בונה העתקות ברירת המחדל יכול לייצר רק את העותק הרדוד.
- עותק רדוד מוגדר כתהליך של יצירת עותק של אובייקט על ידי העתקת נתונים של כל משתני החבר כפי שהם.
בואו נבין זאת באמצעות דוגמה פשוטה:
#include using namespace std; class Demo { int a; int b; int *p; public: Demo() { p=new int; } void setdata(int x,int y,int z) { a=x; b=y; *p=z; } void showdata() { std::cout << 'value of a is : ' < <a<< std::endl; std::cout << \'value of b is : \' < <b<< *p <<*p<< } }; int main() { demo d1; d1.setdata(4,5,7); d2="d1;" d2.showdata(); return 0; pre> <p> <strong>Output:</strong> </p> <pre> value of a is : 4 value of b is : 5 value of *p is : 7 </pre> <img src="//techcodeview.com/img/c-tutorial/75/c-copy-constructor-3.webp" alt="C++ Copy Constructor"> <p>In the above case, a programmer has not defined any constructor, therefore, the statement <strong>Demo d2 = d1;</strong> calls the default constructor defined by the compiler. The default constructor creates the exact copy or shallow copy of the existing object. Thus, the pointer p of both the objects point to the same memory location. Therefore, when the memory of a field is freed, the memory of another field is also automatically freed as both the fields point to the same memory location. This problem is solved by the <strong>user-defined constructor</strong> that creates the <strong>Deep copy</strong> .</p> <h2>Deep copy</h2> <p>Deep copy dynamically allocates the memory for the copy and then copies the actual value, both the source and copy have distinct memory locations. In this way, both the source and copy are distinct and will not share the same memory location. Deep copy requires us to write the user-defined constructor.</p> <p>Let's understand this through a simple example.</p> <pre> #include using namespace std; class Demo { public: int a; int b; int *p; Demo() { p=new int; } Demo(Demo &d) { a = d.a; b = d.b; p = new int; *p = *(d.p); } void setdata(int x,int y,int z) { a=x; b=y; *p=z; } void showdata() { std::cout << 'value of a is : ' < <a<< std::endl; std::cout << \'value of b is : \' < <b<< *p <<*p<< } }; int main() { demo d1; d1.setdata(4,5,7); d2="d1;" d2.showdata(); return 0; pre> <p> <strong>Output:</strong> </p> <pre> value of a is : 4 value of b is : 5 value of *p is : 7 </pre> <img src="//techcodeview.com/img/c-tutorial/75/c-copy-constructor-4.webp" alt="C++ Copy Constructor"> <p>In the above case, a programmer has defined its own constructor, therefore the statement <strong>Demo d2 = d1;</strong> calls the copy constructor defined by the user. It creates the exact copy of the value types data and the object pointed by the pointer p. Deep copy does not create the copy of a reference type variable.</p> <h2>Differences b/w Copy constructor and Assignment operator(=)</h2> <table class="table"> <tr> <th>Copy Constructor</th> <th>Assignment Operator</th> </tr> <tr> <td>It is an overloaded constructor.</td> <td>It is a bitwise operator.</td> </tr> <tr> <td>It initializes the new object with the existing object.</td> <td>It assigns the value of one object to another object.</td> </tr> <tr> <td>Syntax of copy constructor: <br> Class_name(const class_name &object_name) <br> { <br> // body of the constructor. <br> }</td> <td>Syntax of Assignment operator: <br> Class_name a,b; <br> b = a;</td> </tr> <tr> <td><ul> <li>The <strong>copy constructor</strong> is invoked when the new object is initialized with the existing object.</li> <li>The object is passed as an argument to the function.</li> <li>It returns the object.</li> </ul></td> <td>The <strong>assignment operator</strong> is invoked when we assign the existing object to a new object.</td> </tr> <tr> <td>Both the existing object and new object shares the different memory locations.</td> <td>Both the existing object and new object shares the same memory location.</td> </tr> <tr> <td>If a programmer does not define the copy constructor, the compiler will automatically generate the implicit default copy constructor. </td> <td>If we do not overload the '=' operator, the bitwise copy will occur.</td> </tr> </table> <hr></a<<></pre></a<<>
במקרה הנ'ל, מתכנת לא הגדיר שום בנאי, לכן, ההצהרה הדגמה d2 = d1; קורא לבנאי ברירת המחדל שהוגדר על ידי המהדר. בנאי ברירת המחדל יוצר את העותק המדויק או העותק הרדוד של האובייקט הקיים. לפיכך, המצביע p של שני האובייקטים מצביע על אותו מיקום זיכרון. לכן, כאשר זיכרון של שדה משוחרר, הזיכרון של שדה אחר משתחרר גם הוא אוטומטית שכן שני השדות מצביעים על אותו מיקום זיכרון. בעיה זו נפתרת על ידי ה בנאי מוגדר על ידי משתמש שיוצר את עותק עמוק .
עותק עמוק
העתקה עמוקה מקצה באופן דינמי את הזיכרון עבור העותק ולאחר מכן מעתיקה את הערך האמיתי, הן למקור והן לעותק יש מיקומי זיכרון שונים. בדרך זו, גם המקור וגם העותק נפרדים ולא יחלקו את אותו מיקום זיכרון. העתקה עמוקה מחייבת אותנו לכתוב את הבנאי המוגדר על ידי המשתמש.
בואו נבין זאת באמצעות דוגמה פשוטה.
מחרוזת לצ'אר ב-java
#include using namespace std; class Demo { public: int a; int b; int *p; Demo() { p=new int; } Demo(Demo &d) { a = d.a; b = d.b; p = new int; *p = *(d.p); } void setdata(int x,int y,int z) { a=x; b=y; *p=z; } void showdata() { std::cout << 'value of a is : ' < <a<< std::endl; std::cout << \'value of b is : \' < <b<< *p <<*p<< } }; int main() { demo d1; d1.setdata(4,5,7); d2="d1;" d2.showdata(); return 0; pre> <p> <strong>Output:</strong> </p> <pre> value of a is : 4 value of b is : 5 value of *p is : 7 </pre> <img src="//techcodeview.com/img/c-tutorial/75/c-copy-constructor-4.webp" alt="C++ Copy Constructor"> <p>In the above case, a programmer has defined its own constructor, therefore the statement <strong>Demo d2 = d1;</strong> calls the copy constructor defined by the user. It creates the exact copy of the value types data and the object pointed by the pointer p. Deep copy does not create the copy of a reference type variable.</p> <h2>Differences b/w Copy constructor and Assignment operator(=)</h2> <table class="table"> <tr> <th>Copy Constructor</th> <th>Assignment Operator</th> </tr> <tr> <td>It is an overloaded constructor.</td> <td>It is a bitwise operator.</td> </tr> <tr> <td>It initializes the new object with the existing object.</td> <td>It assigns the value of one object to another object.</td> </tr> <tr> <td>Syntax of copy constructor: <br> Class_name(const class_name &object_name) <br> { <br> // body of the constructor. <br> }</td> <td>Syntax of Assignment operator: <br> Class_name a,b; <br> b = a;</td> </tr> <tr> <td><ul> <li>The <strong>copy constructor</strong> is invoked when the new object is initialized with the existing object.</li> <li>The object is passed as an argument to the function.</li> <li>It returns the object.</li> </ul></td> <td>The <strong>assignment operator</strong> is invoked when we assign the existing object to a new object.</td> </tr> <tr> <td>Both the existing object and new object shares the different memory locations.</td> <td>Both the existing object and new object shares the same memory location.</td> </tr> <tr> <td>If a programmer does not define the copy constructor, the compiler will automatically generate the implicit default copy constructor. </td> <td>If we do not overload the '=' operator, the bitwise copy will occur.</td> </tr> </table> <hr></a<<>
במקרה הנ'ל, מתכנת הגדיר בנאי משלו, ולכן ההצהרה הדגמה d2 = d1; קורא לבנאי ההעתקה שהוגדר על ידי המשתמש. הוא יוצר את העותק המדויק של נתוני סוגי הערך והאובייקט המצביע על ידי המצביע p. העתקה עמוקה אינה יוצרת עותק של משתנה מסוג הפניה.
הבדלים שחור/לב הבנאי העתק ואופרטור הקצאה(=)
העתק קונסטרוקטור | מפעיל משימה |
---|---|
זה בנאי עמוס מדי. | זה אופרטור ביטחוני. |
זה מאתחל את האובייקט החדש עם האובייקט הקיים. | זה מקצה את הערך של אובייקט אחד לאובייקט אחר. |
תחביר של בנאי העתקות: Class_name(const class_name &object_name) { // גוף הקונסטרוקטור. } | תחביר של אופרטור הקצאה: Class_name a,b; b = a; |
| ה מפעיל משימה מופעל כאשר אנו מקצים את האובייקט הקיים לאובייקט חדש. |
גם האובייקט הקיים וגם האובייקט החדש חולקים את מיקומי הזיכרון השונים. | גם האובייקט הקיים וגם האובייקט החדש חולקים את אותו מיקום זיכרון. |
אם מתכנת לא מגדיר את בנאי ההעתקה, המהדר יפיק אוטומטית את בנאי ההעתקה המובלע כברירת מחדל. | אם לא נעמיס על האופרטור '=', ההעתקה הסיבית תתרחש. |