💻 Exemplos: Capítulo 09: Classes, Construtores e o Padrão RAII

Especialização em Sistemas com C++ • Demonstrações Práticas Compiláveis


🎯 Objetivo dos Exemplos

Demonstrar a pedra fundamental do design moderno em C++: o padrão RAII (Resource Acquisition Is Initialization). Aprender a encapsular recursos do sistema operacional (como manipuladores de arquivo, buffers de memória ou conexões de rede) dentro do ciclo de vida de um objeto de Stack, garantindo liberação determinística no momento em que o escopo é encerrado, mesmo na ocorrência de exceções.


1. Código Fonte Completo (main.cpp)

/**
 * @file main.cpp
 * @brief Implementação de wrapper RAII e ciclo de vida determinístico de objetos em C++20.
 */

#include <iostream>
#include <string>
#include <cstdint>

// 1. Classe RAII: Gerenciador de Recurso de Hardware
class DispositivoRAII {
private:
    std::string m_nome;
    std::uint32_t m_id_registro;
    int* m_buffer_calibracao; // Recurso bruto alocado internamente

public:
    // Construtor com Lista de Inicialização de Membros
    DispositivoRAII(std::string nome, std::uint32_t id)
        : m_nome(std::move(nome)), 
          m_id_registro(id), 
          m_buffer_calibracao(new int[1024]) // Aquisição de Recurso na Inicialização
    {
        std::cout << "[RAII ADQUIRIDO] Dispositivo '" << m_nome 
                  << "' (ID: " << m_id_registro << ") inicializado. Buffer alocado." << '\n';
    }

    // Destrutor Determinístico: Liberação Incondicional do Recurso
    ~DispositivoRAII() {
        delete[] m_buffer_calibracao;
        m_buffer_calibracao = nullptr;
        std::cout << "[RAII LIBERADO]  Dispositivo '" << m_nome 
                  << "' destruido. Buffer de 1024 ints liberado na memoria." << '\n';
    }

    // Regra dos Cinco (Rule of Five): Proibir cópias acidentais para evitar double free
    DispositivoRAII(const DispositivoRAII&) = delete;
    DispositivoRAII& operator=(const DispositivoRAII&) = delete;

    // Permitir transferência de propriedade (Move Semantics)
    DispositivoRAII(DispositivoRAII&& outro) noexcept
        : m_nome(std::move(outro.m_nome)),
          m_id_registro(outro.m_id_registro),
          m_buffer_calibracao(outro.m_buffer_calibracao)
    {
        outro.m_buffer_calibracao = nullptr;
    }

    DispositivoRAII& operator=(DispositivoRAII&& outro) noexcept {
        if (this != &outro) {
            delete[] m_buffer_calibracao;
            m_nome = std::move(outro.m_nome);
            m_id_registro = outro.m_id_registro;
            m_buffer_calibracao = outro.m_buffer_calibracao;
            outro.m_buffer_calibracao = nullptr;
        }
        return *this;
    }

    void operar() const {
        std::cout << "  -> Dispositivo '" << m_nome << "' operando em regime nominal." << '\n';
    }
};

void executar_rotina_critica() {
    std::cout << "\n--- Entrando no Escopo da Funcao Critica ---" << '\n';
    
    // Objeto instanciado diretamente na Stack
    DispositivoRAII sensor_pressao("Sensor_Pressao_Vapor", 101);
    sensor_pressao.operar();

    std::cout << "--- Saindo do Escopo da Funcao Critica (Destrutor chamado automaticamente) ---" << '\n';
}

int main() {
    std::cout << "=== CAPÍTULO 09: CLASSES E PADRÃO RAII EM C++20 ===" << '\n';

    executar_rotina_critica();

    std::cout << "\nRotina principal concluida sem nenhum vazamento de memoria (Zero Memory Leak)." << '\n';
    return 0;
}

2. Instruções de Compilação e Execução

# Compilação com GCC / Clang
g++ -std=c++20 -Wall -Wextra -O2 main.cpp -o app_raii
./app_raii

# Compilação com MSVC
cl /std:c++20 /EHsc /W4 /O2 main.cpp /Fe:app_raii.exe
.\app_raii.exe

3. Saída Esperada no Terminal

=== CAPÍTULO 09: CLASSES E PADRÃO RAII EM C++20 ===

--- Entrando no Escopo da Funcao Critica ---
[RAII ADQUIRIDO] Dispositivo 'Sensor_Pressao_Vapor' (ID: 101) inicializado. Buffer alocado.
  -> Dispositivo 'Sensor_Pressao_Vapor' operando em regime nominal.
--- Saindo do Escopo da Funcao Critica (Destrutor chamado automaticamente) ---
[RAII LIBERADO]  Dispositivo 'Sensor_Pressao_Vapor' destruido. Buffer de 1024 ints liberado na memoria.

Rotina principal concluida sem nenhum vazamento de memoria (Zero Memory Leak).