[LHC] [GaroaHC] Re: Ainda sobre memória do Arduino, evitando o "new"

Leandro A. F. Pereira leandro at tia.mat.br
Tue Feb 23 11:43:57 PST 2016


2016-02-23 15:51 GMT-03:00 Alejandro Mesias <ale.mesias at gmail.com>:

> Falta agora descobrir se quando o compilador libera o objeto ele chama o
> destrutor ou se preciso fazer isso manualmente, capaz que manualmente.


Se alocar na pilha, quando sair do escopo, o destrutor é chamado. É comum
em C++ usar um negócio chamado RAII (resource acquisition is
initialization) justamente explorando esse fato. O compilador, inclusive,
garante que a ordem de chamada dos destrutores será feita em ordem reversa
à dos construtores (pilha e tal).

Por exemplo, considere que tenha uma classe:

    class File {
    private:
        FILE *f_;
    public:
        File(const char *path, const char *mode) : f_(fopen(path, mode) {}
        ~File() {
            if (f_) fclose(f_);
        }
        FILE *file() { return f_; }
    };

Se você fizer isso:

   void foo() {
        File arquivo_a("teste.txt", "re");
        File arquivo_b("teste2.txt", "re");

        for (size_t i = 0; i < 100; i++) {
              File arquivo_c("teste3.txt", "re");
        }
   }

Os arquivos "teste.txt", "teste2.txt" serão abertos, "teste3.txt" será
aberto e fechado 100 vezes, o arquivo "teste2.txt" será fechado e depois
"teste.txt" será fechado. Automaticamente. :)

Note que o objeto só teve seu destrutor chamado pois é uma variável "auto"
(no sentido C de auto, ou seja, que é desalocada quando sai do escopo, não
no sentido C++11 de auto, que é um mecanismo de inferência de tipo).

Se o objeto tivesse sido alocado com new, isso não aconteceria. Mas, hoje
em dia, não há muitos motivos para se usar new e delete; prefira usar
unique_ptr:

    auto arquivo = std::make_unique<File>("teste.txt", "re");

Assim a classe é alocada com new pelo make_unique, mas assim que arquivo
sair do escopo, o destrutor é chamado e a memória é liberada. Dá pra
colocar isso dentro de uma classe por exemplo, ou retornar um
std::unique_ptr<T> de funções e deixar o compilador tomar cuidado com o
tempo de vida do teu objeto.

BTW, RAII é bem massa. Um exemplo legal é o std::lock_guard, que trava um
std::mutex no construtor e destrava no destrutor, então rola algo assim:

     while (true) {
          std::lock_guard guard(mutex_);

          vetor_compartilhado_.push_back(foo());
     }

Assim, mesmo se o std::vector::push_back() explodir com uma exceção ou se a
função for mais complexa e tiver vários pontos de saída, o destrutor do
lock_guard será chamado sempre.

-- 
 Leandro
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listas.tia.mat.br/pipermail/hsc-tia.mat.br/attachments/20160223/ee503d95/attachment-0001.html>


More information about the HSC mailing list