[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