#include <iostream>
#include <string>
#include <vector>
using namespace std;

class IntVector
{
   public:
   
      vector<int*> elements;

      // default constructor   
      IntVector() { cout << "\ndefault constructor\n\n"; }
      
      // destructor
     ~IntVector() { cout << "\ndestructor\n"; clear(); }
      
      // copy constructor   
      IntVector(const IntVector& src);
      
      // assignment
      IntVector& operator=(const IntVector& src);

      // adiciona um elemento
      void add(int i) { elements.push_back(new int(i)); }

      // libera elementos   
      void clear();
      
      // imprime elementos   
      void print(const string& msg);
      
   private:

      // copia elementos   
      void copy(const IntVector& src);
};

void IntVector::clear()
{
   cout << "liberando memoria\n";
   
   for (auto ptr : elements)
       delete ptr;
       
   elements.clear();
}

void IntVector::copy(const IntVector& src)
{
   cout << "copiando elementos\n";
   
   for (auto srcP : src.elements)
   {
      // cria um ponteiro e inicializa com o valor correspondente
      int* newP(new int(*srcP));
      elements.push_back(newP);
    }
}

// copy constructor
IntVector::IntVector(const IntVector& src)
{
   cout << "\ncopy constructor\n";
   copy(src);
}

// assignment
IntVector& IntVector::operator=(const IntVector& src)
{
   cout << "assignment\n";
   
   // libera os elementos atuais
   clear();

   // copia novos elementos
   copy(src);
}

void IntVector::print(const string& msg)
{
   cout << msg <<": [";
   
   for (auto p : elements)
       cout << " " << *p;
       
    cout << "]\n";
}


int main()
{
   // default constructor
   IntVector v1;
   
   v1.add(1);
   v1.add(2);
   v1.add(3);
   v1.add(4);
   v1.add(5);
   
   v1.print("v1");
   
   // copy constructor
   IntVector v2 { v1 };
   v2.print("v2");
 
   IntVector v3;
 
   v3 = v1;  
   v3.print("v3");
}