irmantas_radavicius

Untitled

Apr 16th, 2026
65
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.28 KB | None | 0 0
  1. // deep copying in C++
  2. // 2026-04-16
  3. // tested on Win with g++
  4.  
  5. #include <iostream>
  6. #include <sstream>
  7. #include <fstream>
  8.  
  9. #include <exception>
  10. #include <stdexcept>
  11.  
  12. #include <cfloat>
  13. #include <cassert>
  14. #include <cstdlib>
  15. #include <cstdio>
  16.  
  17. using namespace std;
  18.  
  19. class X {
  20.     // the field below is the one that needs a special care
  21.     int *data;
  22.     int size;
  23. public:
  24.     X(int size){
  25.         data = new int[size];
  26.     }
  27.     // we provide the copy constructor and implement a deep copy
  28.     X(const X& other){
  29.         // this would be copied in the shallow copy
  30.         // but since we provide our own copy constructor
  31.         // default functionality becomes disabled thus we need
  32.         // to do all the copying ourselves
  33.         size = other.size;
  34.        
  35.         // this is the main thing - allocate the memory for the field
  36.         // so that it lives a separate life from the original
  37.         data = new int[size];
  38.        
  39.         // carefully transfer all the contents
  40.         // generally if you have pointer-to-pointer-to-pointer
  41.         // you might go deeper - hence the name "deep copy"
  42.         // i.e. you propagate copying into deeper levels
  43.         for(int i = 0; i < size; ++i){
  44.             data[i] = other.data[i];
  45.         }
  46.     }
  47.     // copy constructor is not enough, you also have to
  48.     // provide assignment operator
  49.     // Object x(copy); - this is copy constructor
  50.     // Object x = copy; - this is also copy constructor!
  51.     // x = copy; - this is the assignment as no new object is created
  52.     const X& operator=(const X& other){
  53.         // self check is an essential part, because of the delete
  54.         // if there is self-assignment i.e. x = x, we delete x1
  55.         // and then there is no more data to copy;
  56.         // but for self assignment we do not need to do anything
  57.         // because nothing changes
  58.         if(this != &other){
  59.            
  60.             // delete is the step that is needed
  61.             // when compared to copy constructor
  62.             // because we have to deal with the
  63.             // old data which becomes irrelevant
  64.             delete [] data;
  65.            
  66.             // now the rest follows as in copy-constructor
  67.             size = other.size;
  68.             data = new int[size];
  69.             for(int i = 0; i < size; ++i){
  70.                 data[i] = other.data[i];
  71.             }
  72.         }
  73.         return other;
  74.     }
  75.    
  76.     // destructor - the fact that we needed it for a class
  77.     // to function properly, is a sign to apply the rule of three
  78.     // thus we examine if we need deep copying because
  79.     // shallow copying might fail us
  80.     ~X(){
  81.         delete [] data;
  82.     }
  83.    
  84.    
  85.     int get(int pos){
  86.         return data[pos];
  87.     }
  88.     void set(int pos, int value){
  89.         data[pos] = value;
  90.     }
  91.  
  92.    
  93. };
  94.  
  95. int main(){
  96.    
  97.     try {
  98.         cout << "Hello" << endl;
  99.        
  100.         // original object
  101.         X* x1 = new X(5);
  102.         x1->set(0, 2);
  103.         x1->set(1, 4);
  104.         cout << x1->get(0) << x1->get(1) << endl;
  105.        
  106.         // another object
  107.         X x2(6); // you can use the X x2(*x1) if you want constructor
  108.        
  109.         // assignment operation
  110.         x2 = *x1;
  111.        
  112.         // this is disaster if shallow copy is done
  113.         // test this by commenting out the two operations provided
  114.         // and see what happens
  115.         delete x1;
  116.         x2.get(0);
  117.        
  118.         // this is just to check where the code crashes
  119.         // i.e. if the line is reached, if your system doesn't show it
  120.         cout << "Hello" << endl;
  121.        
  122.     } catch(...){
  123.         cout << "Unexpected exception" << endl;
  124.     }
  125.    
  126.     // checking also if this was reached, if not - it means
  127.     // the program has crashed
  128.     cout << "Hello" << endl;
  129.  
  130.     return 0;
  131. }
Advertisement
Add Comment
Please, Sign In to add comment