Utilize o Construtor de Cópia em C++

Jinku Hu 12 outubro 2023
  1. Use o Construtor de Cópia para inicializar um objeto de outro objeto do mesmo tipo em C++
  2. Use o Operador de Atribuição de Cópia para Definir a Sobrecarga do Operador de Atribuição para o Objeto em C++
Utilize o Construtor de Cópia em C++

Este artigo explica vários métodos de como utilizar um construtor de cópia em C++.

Use o Construtor de Cópia para inicializar um objeto de outro objeto do mesmo tipo em C++

Existem várias operações na classe chamadas coletivamente de controle de cópia. Essas operações definem como os objetos de um determinado tipo de classe são copiados, movidos, atribuídos ou destruídos. Neste artigo, vamos nos concentrar apenas no construtor de cópia e na atribuição de cópia.

O construtor de cópia inicializa o objeto duplicando o valor do argumento passado como referência (normalmente é passado como referência const). A classe não é necessária para definir o construtor de cópia como qualquer outra operação de controle de cópia porque o compilador define automaticamente as operações sintetizadas para as indefinidas. Ainda assim, muitas vezes, os últimos podem causar problemas. O construtor de cópia sintetizado copia cada membro do objeto de argumento para o objeto que está sendo criado. Pode haver membros de alguns outros tipos de classe, que são copiados por seu construtor de cópia. Em contraste, os objetos de tipo embutidos são copiados diretamente.

O código de exemplo a seguir demonstra o comportamento do construtor de cópia de MyClass, que recebe o único argumento obrigatório para o construtor de cópia e, em seguida, inicializa os membros de dados. Por outro lado, o construtor de cópia pode ter argumentos adicionais, que devem ser opcionais e ter valores padrão.

Quando o objeto do tipo MyClass é criado primeiro, o construtor padrão é chamado; entretanto, se atribuirmos m1 à variável m3 recém-criada, o construtor de cópia é chamado. A última operação também é chamada de inicialização de cópia, que pode utilizar um construtor de cópia ou mover um construtor (discutido em outro artigo).

#include <iostream>

using std::cout;
using std::endl;
using std::pair;

class MyClass {
 private:
  int n1{};
  int n2{};

 public:
  MyClass(int x, int y) : n1(x), n2(y) {
    cout << "Constructor 1 is called" << endl;
  };

  MyClass(const MyClass& src) {
    cout << "Copy Constructor is called " << endl;
    n1 = src.n1;
    n2 = src.n2;
  }

  auto getPair() { return pair<int, int>(n1, n2); }

  ~MyClass() = default;
};

int main() {
  MyClass m1(12, 21);
  cout << "------------------" << endl;
  MyClass m2(11, 33);
  cout << "------------------" << endl;
  MyClass m3 = m1;
  cout << "------------------" << endl;

  cout << m1.getPair().first << m1.getPair().second << endl;
  cout << m2.getPair().first << m2.getPair().second << endl;
  cout << m3.getPair().first << m3.getPair().second << endl;

  return EXIT_SUCCESS;
}

Resultado:

Constructor 1 is called-- -- -- -- -- -- -- -- --Constructor 1 is
    called-- -- -- -- -- -- -- -- --Copy Constructor is
        called-- -- -- -- -- -- -- -- --1221 1133 1221

Use o Operador de Atribuição de Cópia para Definir a Sobrecarga do Operador de Atribuição para o Objeto em C++

O operador de atribuição de cópia define como atribuir objetos do mesmo tipo. O compilador também sintetiza essa operação se o usuário não a definir explicitamente. A atribuição de cópias é descrita de forma semelhante a outras funções de sobrecarga do operador. Leva um argumento do mesmo tipo que a classe e geralmente retorna a referência ao operando à esquerda. Um operador de atribuição de cópia deve ser definido como uma função de membro.

O próximo trecho de código adiciona o operador de atribuição de cópia para MyClass e o invoca enquanto atribui o objeto m2 a m1.

#include <iostream>

using std::cout;
using std::endl;
using std::pair;

class MyClass {
 private:
  int n1{};
  int n2{};

 public:
  MyClass(int x, int y) : n1(x), n2(y) {
    cout << "Constructor 1 is called" << endl;
  };

  MyClass(const MyClass& src) {
    cout << "Copy Constructor is called " << endl;
    n1 = src.n1;
    n2 = src.n2;
  }

  MyClass& operator=(const MyClass& src) {
    cout << "Copy Assignment is called " << endl;
    n1 = src.n1;
    n2 = src.n2;
    return *this;
  }

  auto getPair() { return pair<int, int>(n1, n2); }

  ~MyClass() = default;
};

int main() {
  MyClass m1(12, 21);
  cout << "------------------" << endl;
  MyClass m2(11, 33);
  cout << "------------------" << endl;
  MyClass m3 = m1;
  cout << "------------------" << endl;
  m1 = m2;
  cout << "------------------" << endl;

  cout << m1.getPair().first << m1.getPair().second << endl;
  cout << m2.getPair().first << m2.getPair().second << endl;
  cout << m3.getPair().first << m3.getPair().second << endl;

  return EXIT_SUCCESS;
}

Resultado:

Constructor 1 is called-- -- -- -- -- -- -- -- --Constructor 1 is
    called-- -- -- -- -- -- -- -- --Copy Constructor is
        called-- -- -- -- -- -- -- -- --Copy Assignment is
            called-- -- -- -- -- -- -- -- --1221 1133 1221
Autor: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook