Idioma Copy-and-Swap em C++: guia 2025 com exemplos

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

O que é o Idioma Copy-and-Swap e por que é indispensável em 2025



Imagine que você está escrevendo uma classe para trabalhar com memória dinâmica. Tudo vai bem, até chegar na sobrecarga do operador de atribuição. Você escreve operator=, verifica a auto-atribuição, libera manualmente os recursos antigos, aloca novos… E em 90% dos casos comete um bug que leva a vazamento de memória ou dupla exclusão. Familiar?



Em C++, existe uma solução elegante — o idioma copy-and-swap. Não é apenas um truque da moda, mas uma técnica fundamental que permite escrever código seguro, resistente a exceções e conciso. Em 2025, quando C++23 já está ativamente em uso e o padrão C++26 está no horizonte, esse idioma continua sendo o padrão ouro para classes que gerenciam recursos.



Neste artigo, vamos analisar o idioma copy-and-swap do início ao fim: começando pelo problema que ele resolve, até exemplos práticos e melhores práticas de 2025. Prepare o compilador — vai ter muito código!



O problema: por que o operator= ingênuo é prejudicial



Vamos começar com um exemplo clássico de uma classe que gerencia um array dinâmico. Sem o idioma copy-and-swap, o código geralmente se parece com isso:



class DumbArray {public:    DumbArray(size_t size)         : size_(size), data_(new int[size]) {}        ~DumbArray() { delete[] data_; }        // Operador de atribuição ingênuo    DumbArray& operator=(const DumbArray& other) {        if (this == &other) return *this; // verificação de auto-atribuição        delete[] data_;                    // libera recursos antigos        size_ = other.size_;        data_ = new int[size_];           // aloca novos        std::copy(other.data_, other.data_ + size_, data_);        return *this;    }    private:    size_t size_;    int* data_;};


À primeira vista, tudo parece lógico. Mas existem três problemas:

  • Falta de garantia básica de exceções. Se new int[size_] lançar std::bad_alloc, o objeto permanece em um estado inválido: data_ apontará para memória excluída.
  • Duplicação de lógica. A cópia de dados já está implementada no construtor de cópia. Por que estamos escrevendo a mesma coisa manualmente?
  • Verificação de auto-atribuição. Ela torna o código mais lento e é facilmente esquecida. Além disso, em 95% dos casos a auto-atribuição não ocorre, mas a verificação ainda é executada.


E isso não é tudo. Se você adicionar outros recursos à classe (como descritores de arquivo ou mutexes), o código se torna não apenas pesado — ele se torna perigoso. É aqui que o idioma copy-and-swap entra em cena.



A essência do idioma: três passos para um operator= ideal



O idioma copy-and-swap é baseado em uma ideia simples: não escreva a lógica de cópia no operador de atribuição — use o construtor de cópia e a função swap. O algoritmo é o seguinte:



  1. Copy: criamos uma cópia temporária do objeto usando o construtor de cópia.
  2. Swap: trocamos o conteúdo do objeto atual com a cópia temporária.
  3. Destroy: o objeto temporário é destruído, liberando os recursos antigos.


No código, fica assim:



class SmartArray {public:    SmartArray(size_t size = 0)         : size_(size), data_(size ? new int[size] : nullptr) {}        // Construtor de cópia    SmartArray(const SmartArray& other)         : size_(other.size_), data_(other.size_ ? new int[other.size_] : nullptr) {        std::copy(other.data_, other.data_ + size_, data_);    }        // Destrutor    ~SmartArray() { delete[] data_; }        // Função swap amiga    friend void swap(SmartArray& first, SmartArray& second) noexcept {        using std::swap;        swap(first.size_, second.siz                

Blogs

Book Recommendations