How to use Operator= to copy a pointer vector?

Asked

Viewed 909 times

2

Having this class, I would like to implement, operator =, copy the pointer vector to int for another vector, it is obligatory to reserve memory before doing so?

What’s the difference between making a constructor per copy and implementing the attribution operator? Copy constructor makes only one copy of the object, while assignment operator changes the content (in this case)?

class ints{
private:
  vector <int*> inteiros;
public: 
  ints & operator=(const ints & i1);
}

2 answers

2


How to use Operator= to copy a pointer vector?

The operador = is already set to vector<int*>

it is obligatory to reserve memory before doing so?

No. Memory allocation by std::vector is automatic. Do not, however, confuse memory for pointers with memory for integers to which pointers point. I mean, if you copy one vector of pointers to another, both will point to the same integers.

What’s the difference between making a constructor per copy and implementing the attribution operator? Copy constructor makes only one copy of the object, while assignment operator changes the content (in this case)?

They are different things. One is constructor and generates a new object; Another is an operator that operates on an existing object.

Generally, it is expected that when an object is created as a copy of another the result will be equal objects. That is, after we create B in the form Objeto B(A), we hope that B==A

Generally, it is expected that when one object is assigned to another, the result will be equal objects. That is, after we apply B=A, it is expected that B==A

Note that one usually expects the same result through the two operations, but they are different things and you can implement each as you want.

I hope the example below is enlightening, realize that I do not create neither the assignment operator nor the constructor. I let the compiler automatically generate them:

class ints
{
public:
  //vetor de ponteiros para int
  std::vector<int*> inteiros;
  //função que imprime valor de todos inteiros apontados
  void escreve()
  {
    for(auto i:inteiros)
      std::cout << *i << ", ";
    std::cout << std::endl;
  }
};

Creating an object ints A and saving in the vector of this some pointers:

//declara 3 ints
int x = 1;
int y = 2;
int z = 3;
//cria objeto A da classe ints
ints A;
//salva ponteiros em A 
A.inteiros.push_back(&x);
A.inteiros.push_back(&y);
A.inteiros.push_back(&z);

Creating an object by copying A:

//cria objeto B através de cópia
ints B(A);

Creating an object and using attribution to match it to A:

//cria objeto C e usa operador atribuição
ints C;
C = A;

Having the contents printed, it turns out that the objects point to the same integers x, y and z initially declared:

//verifica conteúdo
A.escreve();
B.escreve();
C.escreve();

(terminal result)

1, 2, 3, 
1, 2, 3, 
1, 2, 3, 

All objects contain vectors that point to the same integers, that is, the value of the pointers saved in the vectors were all copied from A. One can verify this by changing the value of any of the integers pointed:

//A, B e C apontam para os mesmos inteiros, incluindo y
y = 666;
//verifica-se que a mudança é visível através de todos objetos:
A.escreve();
B.escreve();
C.escreve();

(terminal result)

1, 666, 3, 
1, 666, 3, 
1, 666, 3, 

Here is the example above online.

1

Usually classes that have pointers as members need to implement 3 methods: copy constructor, assignment and destructor.

It may also be necessary to implement the "move constructor" and "move assignment" methods, but it is more rare (this is a new feature that entered C++11).

Below is an example implementing the first 3 methods cited.

This implementation does not address the exotic cases of copy constructor and assignment where the two operands are the same (e. g.: "x = x").

#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;

   // assignment
   v3 = v1;  
   v3.print("v3");
}

See working in http://ideone.com/jJVwJd.

  • I think I understand the reinforcement you wanted to give in the dynamic memory manipulation, but if each vector pointer owns the integer that points, why not use a direct vector<int>?

  • I am attending to the context of the question.... in addition, I tried to be didactic: classes that have pointers as members usually need constructor, copy constructor and destructor...besides, from C++11 it is not advisable to use "Naked pointers", but "unique_ptr" and "shared_ptr"

Browser other questions tagged

You are not signed in. Login or sign up in order to post.