AnyCompiler

Constructors e RAII

Um destructor, escrito como o nome da class prefixado com ~, roda automaticamente quando um object sai de scope — deterministicamente, não em algum ponto posterior imprevisível como o finalizer de um coletor de lixo poderia fazer. Esse pareamento de um constructor que adquire um recurso com um destructor que o libera é RAII: Resource Acquisition Is Initialization.

#include <iostream>
using namespace std;

class Logger {
public:
    Logger() {
        cout << "Logger created" << endl;
    }
    ~Logger() {
        cout << "Logger destroyed" << endl;
    }
};

int main() {
    cout << "Before scope" << endl;
    {
        Logger log;
        cout << "Inside scope" << endl;
    }
    cout << "After scope" << endl;
    return 0;
}
Output
Before scope
Logger created
Inside scope
Logger destroyed
After scope

Note a ordem exata: o destructor roda no instante em que log sai do seu bloco envolvente, antes mesmo de 'After scope' ser impresso. Essa é a ideia central por trás de todo tipo que gerencia recursos em C++ — file handles, locks, e os smart pointers abordados mais adiante neste curso todos se apoiam exatamente nesse mecanismo, em vez do timing indeterminado de um coletor de lixo.

A seguir: encapsulation — controle de acesso, e por que tornar fields private importa quando uma class tem invariantes a proteger.

Practice exercise

Defina uma class Counter cujo constructor imprima "Counter started" e cujo destructor imprima "Counter finished". Crie um Counter em main, imprima "Running" depois de criá-lo, depois deixe-o sair de scope.