Você está na página 1de 6

13/05/2019

Introdução

▪ Gerenciamento explícito da memória


▪ new / delete (single variables)
Programação e Desenvolvimento de Software 2 ▪ new[] / delete[] (array variables)
Programação Orientada a Objetos (Gerenciando Memória)
Prof. Douglas G. Macharet
▪ Prós/Cons
douglas.macharet@dcc.ufmg.br
▪ Uso eficiente da memória
▪ Fácil ter programas problemáticos
▪ Requer compreensão do modelo de memória e
das operações próprias de gerenciamento

PDS 2 - Programação Orientada a Objetos (Gerenciando Memória) 2

Introdução Introdução

▪ Mau gerenciamento de memória ▪ Construtores


▪ Usar variáveis não inicializadas ▪ Responsáveis por inicializar os membros do
▪ Alocar memória e não excluí-la objeto após a alocação na memória
▪ Tentar acessar um valor após excluído ▪ Construtor de cópia
▪ Boas práticas ▪ Padrão / User-defined
▪ Sempre inicializar as variáveis ▪ Recebe um objeto como argumento e copia os
valores dos membros para o outro objeto
▪ Sempre liberar a memória após o uso
▪ Shallow / Deep
▪ Certifique-se sempre de que a memória não
▪ Copiar endereço / Copiar valor em novo endereço
está mais em uso antes de excluí-lo!
https://en.wikipedia.org/wiki/Copy_constructor_(C%2B%2B)

PDS 2 - Programação Orientada a Objetos (Gerenciando Memória) 3 PDS 2 - Programação Orientada a Objetos (Gerenciando Memória) 4

Introdução Introdução
Exemplo 1 Exemplo 1

int main() { 10 20
10 30
ClasseTeste c1; 10 30
class ClasseTeste {
public: c1.x = 10;
int x, *p; *c1.p = 20;
c1 c2
c1.display();
ClasseTeste() {
x *p x *p
this->p = new int; ClasseTeste c2 = c1;
} 10 10
*c2.p = 30;
c2.display();
void display() {
cout << this->x << " " << *this->p << endl;
} c1.display();
};
20
return 0;
}
30

PDS 2 - Programação Orientada a Objetos (Gerenciando Memória) 5 PDS 2 - Programação Orientada a Objetos (Gerenciando Memória) 6

1
13/05/2019

Introdução Introdução
Exemplo 1

class ClasseTeste { ▪ Regra simples


public:
int x, *p; ▪ Sempre que o operador new for usado, deve-se ser
ClasseTeste() { capaz de identificar quando a exclusão será feita
this->p = new int;
} Construtor de cópia
▪ Formas de evitar problemas
▪ Ocultar a alocação de memória em um objeto,
ClasseTeste(ClasseTeste &source) {
this->x = source.x;
this->p = new int;
*this->p = *source.p; fazendo com que o objeto seja responsável
}
▪ Ao ser destruído, ele deve excluir essa memória
void display() {
cout << this->x << " " << *this->p << endl; ▪ Manter uma contagem das referências
}
}; ▪ Operadores/ferramentas auxiliares da linguagem
https://wandbox.org/permlink/478E3fTAXoZERy7g

PDS 2 - Programação Orientada a Objetos (Gerenciando Memória) 7 PDS 2 - Programação Orientada a Objetos (Gerenciando Memória) 8

Introdução Introdução
Exemplo 2

▪ Destrutores class ClasseTeste {


public:

▪ Responsáveis por desalocar qualquer memória


int *x, *p;

ClasseTeste() {

dinâmica (ponteiros) associada aos membros this->x = new int;


if (this->x == nullptr) {
cout << "Memoria insuficiente!" << endl;

▪ Utilize, mas entenda os riscos }


exit(1);

▪ Não são chamados em algumas situações this->p = new int;


if (this->p == nullptr) {
cout << "Memoria insuficiente!" << endl;
▪ Término prematuro do programa (exit) }
exit(1);

▪ Lançamento de exceção no construtor


}

~ClasseTeste() {
▪ Remoção por um ponteiro base, sem dtor virtual delete this->x;
delete this->p;
}
};

https://wandbox.org/permlink/rD11A24OmEPMUy8U

PDS 2 - Programação Orientada a Objetos (Gerenciando Memória) 9 PDS 2 - Programação Orientada a Objetos (Gerenciando Memória) 10

Introdução Introdução
Exemplo 3 Exemplo 3
Circunferencia.hpp
main.cpp
#ifndef M_PI
#define M_PI 3.14159265358979323846 #include <iostream>
#endif
#include "Ponto.hpp"
#ifndef CIRCUNFERENCIA_H Circunferencia.cpp #include "Circunferencia.hpp"
#define CIRCUNFERENCIA_H
#include "Circunferencia.hpp"
using namespace std;
#include <cmath>
Circunferencia::Circunferencia(Ponto* centro, double raio) {
#include "Ponto.hpp" this->_centro = centro; int main() {
this->_raio = raio;
class Circunferencia { } Circunferencia* c1 = new Circunferencia(new Ponto(), 10);
cout << c1->calcularArea() << endl;
public: Circunferencia::~Circunferencia() {
Ponto* _centro; delete this->_centro;
Ponto p(5.0, 5.0);
• Ponteiro externo?
}
Circunferencia* c2 = new Circunferencia(&p, •10);
double _raio; Instanciar dentro de Circunferencia?
Circunferencia(Ponto* centro, double raio); double Circunferencia::calcularArea() { cout << c2->calcularArea() << endl;
~Circunferencia(); return M_PI * pow(this->_raio, 2);
} delete c1;
double calcularArea(); delete c2;

};
return 0;
#endif
}

PDS 2 - Programação Orientada a Objetos (Gerenciando Memória) 11 PDS 2 - Programação Orientada a Objetos (Gerenciando Memória) 12

2
13/05/2019

Rule of Three Rule of Three


Exemplo

▪ Se um (ou mais) dos seguintes membros foi definido,


provavelmente deve-se definir todos os três:
class Test { int main() {
public: Test t1, t2;
Test() {
▪ Destrutor
t2 = t1;
cout << "Constructor called." << endl;
} Test t3 = t1;

▪ Construtor de cópia
return 0;
~Test() { }

▪ Operador de cópia
cout << “Destructor called." << endl;
}

Constructor called.
▪ Se a versão gerada pelo compilador para uma não se Test(const Test &t) {
cout << "Copy constructor called." << endl; Constructor called.
ajusta às necessidades da classe em questão, então } Assignment operator called.
Copy constructor called.
provavelmente as outras funções padrões também não Test& operator = (const Test &t) {
cout << "Assignment operator called." << endl; Destructor called.
return *this;
}
Destructor called.
}; Destructor called.

https://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming)

PDS 2 - Programação Orientada a Objetos (Gerenciando Memória) 13 PDS 2 - Programação Orientada a Objetos (Gerenciando Memória) 14

Resource Acquisition Is Initialization (RAII) Smart Pointers (C++11)

▪ Conceito em C ++ que aproveita a propriedade ▪ Classes auxiliares que envolvem ponteiros e


essencial da Pilha para simplificar o gerenciamento sobrecarregam os operadores -> e *
de memória de objetos no Heap
▪ Gerenciamento automático de memória
▪ Vincula recursos ao lifetime do objeto, que pode
▪ Quando um ponteiro inteligente não está mais
não coincidir com a entrada/saída de um escopo
em uso (sai do escopo), a memória para a qual
▪ Princípio ele aponta é desalocada automaticamente
▪ Envolver o recurso (um ponteiro) em um outro ▪ Tipos
objeto e descartar o recurso em seu destrutor ▪ std::unique_ptr
▪ std::shared_ptr
https://en.cppreference.com/w/cpp/language/raii
https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization https://en.wikipedia.org/wiki/Smart_pointer

PDS 2 - Programação Orientada a Objetos (Gerenciando Memória) 15 PDS 2 - Programação Orientada a Objetos (Gerenciando Memória) 16

Smart Pointers (C++11) Smart Pointers (C++11)


Exemplo 1

▪ std::unique_ptr
▪ Possui um recurso alocado dinamicamente class ClasseA {
▪ Apenas ele pode apontar para o recurso public:
int id;

▪ std::shared_ptr ClasseA(int id) : id(id) {


cout << "ClasseA::Constructor:"<< this->id << endl;
▪ Possui um recurso alocado compartilhado }

▪ Mantém um contador interno com o número ~ClasseA() {


cout << "ClasseA::Destructor:"<< this->id << endl;
de shared_ptr que possuem o mesmo recurso };
}

PDS 2 - Programação Orientada a Objetos (Gerenciando Memória) 17 PDS 2 - Programação Orientada a Objetos (Gerenciando Memória) 18

3
13/05/2019

Smart Pointers (C++11) Smart Pointers (C++11)


Exemplo 1 Exemplo 2

int main() { ClasseA::Constructor:1


int main() { ClasseA::Constructor:1 unique_ptr<ClasseA> c1(new ClasseA(1)); ClasseA::Constructor:2
ClasseA::Constructor:2 2
// Compile Error : unique_ptr object is not copyable
ClasseA c1(1); ClasseA::Constructor:3 //unique_ptr<ClasseA> c2 = c1;
1
ClasseA::Destructor:3 ClasseA::Destructor:2
shared_ptr<ClasseA> c2(new ClasseA(2)); ClasseA::Destructor:1
ClasseA *c2 = new ClasseA(2); ClasseA::Destructor:1 shared_ptr<ClasseA> c3 = c2;

unique_ptr<ClasseA> c3(new ClasseA(3)); cout << c2.use_count() << endl;

c3 = nullptr;
return 0; cout << c2.use_count() << endl;
}
return 0;
https://wandbox.org/permlink/n9tEfvcvNELNSkGZ }

https://wandbox.org/permlink/xnJ8jOmmBwsYH7Zb

PDS 2 - Programação Orientada a Objetos (Gerenciando Memória) 19 PDS 2 - Programação Orientada a Objetos (Gerenciando Memória) 20

Smart Pointers (C++11) Smart Pointers (C++11)


Exemplo 3 Exemplo 3

class Animal {
#include <list> Au! Au!
public:
virtual void fale() {
int main() {
Miau!
cout << "Fale padrao!" << endl;
}; Au! Au!
list<Animal*> lista; Miau!
~Animal() {
cout << "Animal::Destructor" << endl; Au! Au!
}
for(int i=0; i<5;i++) {
}; if (i % 2 == 0)
lista.push_back(new Cachorro());
else
Memory Leak!
lista.push_back(new Gato()); Nenhum destrutor é chamado!
class Gato : public Animal { class Cachorro : public Animal {
public: public: }
void fale() override { void fale() override {
cout << "Miau!" << endl; cout << "Au! Au!" << endl; for (auto a : lista)
} } a->fale();
~Gato() { ~Cachorro() {
cout << "Gato::Destructor" << endl; cout << "Cachorro::Destructor" << endl; return 0;
} } }
}; };

PDS 2 - Programação Orientada a Objetos (Polimorfismo – 1/2) 21 PDS 2 - Programação Orientada a Objetos (Polimorfismo – 1/2) 22

Smart Pointers (C++11) Smart Pointers (C++11)


Exemplo 3 Exemplo 3

int main() { Au! Au! Au! Au!


list<unique_ptr<Animal>> lista; Miau! Miau!
Au! Au! Au! Au!
for(int i=0; i<5;i++) {
if (i % 2 == 0)
Miau! class Animal { Miau!
lista.push_back(unique_ptr<Animal>(new Cachorro())); Au! Au! public: Au! Au!
else Animal::Destructor virtual void fale() { Cachorro::Destructor
lista.push_back(unique_ptr<Animal>(new Gato())); cout << "Fale padrao!" << endl;
} Animal::Destructor Animal::Destructor
};
Animal::Destructor Gato::Destructor
for (auto const &a : lista)
a->fale();
Animal::Destructor virtual ~Animal() { Animal::Destructor
Animal::Destructor cout << "Animal::Destructor" << endl; Cachorro::Destructor
return 0; } Animal::Destructor
} }; Gato::Destructor
https://wandbox.org/permlink/FHSEtAZIq0pY8sKX Animal::Destructor
Memory Leak! Cachorro::Destructor
Destrutor derivado não é chamado! Animal::Destructor

PDS 2 - Programação Orientada a Objetos (Polimorfismo – 1/2) 23 PDS 2 - Programação Orientada a Objetos (Polimorfismo – 1/2) 24

4
13/05/2019

Exercício Exercício

MensagemBase
- data
- status
Vai ter aula de PDS hj? + exibir()

MensagemTexto MensagemImagem MensagemAudio


- texto - imagem - audio
Blz!

PDS 2 - Programação Orientada a Objetos (Gerenciando Memória) 25 PDS 2 - Programação Orientada a Objetos (Gerenciando Memória) 26

Exercício Exercício
MensagemBase.hpp
#ifndef MENSAGEMBASE_H
#define MENSAGEMBASE_H

#include <ctime> MensagemBase.cpp

enum MsgStatus {
#include "MensagemBase.hpp"
NONE,
SENT, MensagemBase::MensagemBase() {
DELIVERED,
READ
this->_data = std::time(nullptr);
}; this->_status = MsgStatus::NONE;
}
class MensagemBase {

private: std::time_t MensagemBase::getData() {


std::time_t _data; return this->_data;
MsgStatus _status;
}
public:
virtual void exibir() = 0; MsgStatus MensagemBase::getStatus() {
MensagemBase();
return this->_status;
std::time_t getData(); }
MsgStatus getStatus();

};

#endif

https://en.cppreference.com/w/cpp/language/enum https://en.cppreference.com/w/cpp/language/enum

PDS 2 - Programação Orientada a Objetos (Gerenciando Memória) 27 PDS 2 - Programação Orientada a Objetos (Gerenciando Memória) 28

Exercício Exercício
Chat.hpp Chat.cpp
#ifndef CHAT_H #include "Chat.hpp"
#define CHAT_H
void Chat::enviarMensagem(MensagemBase *msg) {
#include <list> this->_historico.push_back(msg);
}
#include <iostream>
void Chat::exibirMensagens() {
#include "MensagemBase.hpp" for (auto m : this->_historico) {
time_t d = m->getData();
#include "MensagemTexto.hpp" char data[20];
#include "MensagemImagem.hpp" strftime(data, 20, "%Y-%m-%d %H:%M:%S", localtime(&d));
#include "MensagemAudio.hpp"
std::cout << "(" << data << ", " << m->getStatus() << ")" << std::endl;
m->exibir();
class Chat { }
}
private:
std::list<MensagemBase*> _historico; void Chat::enviarMensagemTexto(std::string texto) {
MensagemTexto *msg = new MensagemTexto(texto);
void enviarMensagem(MensagemBase* msg);
this->enviarMensagem(msg);
}
public:
void exibirMensagens(); void Chat::enviarMensagemImagem(std::string imagem) {
MensagemImagem *msg = new MensagemImagem(imagem);
void enviarMensagemTexto(std::string texto); this->enviarMensagem(msg);
}
void enviarMensagemImagem(std::string imagem);
void enviarMensagemAudio(std::string audio); void Chat::enviarMensagemAudio(std::string audio) {
MensagemAudio *msg = new MensagemAudio(audio);
}; this->enviarMensagem(msg);
}
#endif

PDS 2 - Programação Orientada a Objetos (Gerenciando Memória) 29 PDS 2 - Programação Orientada a Objetos (Gerenciando Memória) 30

5
13/05/2019

Exercício Exercício
. project
├── Makefile
├── build
main.cpp ├── include
│ └── chat
#include "Chat.hpp"
│ └── Chat.hpp
int main() { │ └── mensagem
│ └── MensagemBase.hpp
Chat chat; │ └── MensagemAudio.hpp
│ └── MensagemImagem.hpp
chat.enviarMensagemTexto("Oi, tem aula de PDS2 hoje?"); │ └── MensagemTexto.hpp
chat.enviarMensagemAudio("audio.wav"); └── imgfiles
chat.enviarMensagemImagem("imagem03.ascii"); └── src
chat.enviarMensagemTexto("Mas que puxa :("); │ └── main.cpp
│ └── chat
chat.exibirMensagens();
│ └── Chat.cpp
│ └── mensagem
return 0;
}
│ └── MensagemBase.cpp
│ └── MensagemAudio.cpp
│ └── MensagemImagem.cpp
│ └── MensagemTexto.cpp

PDS 2 - Programação Orientada a Objetos (Gerenciando Memória) 31 PDS 2 - Programação Orientada a Objetos (Gerenciando Memória) 32

Exercício Exercício

MensagemBase
- data
- status
+ exibir()

MensagemTexto MensagemImagem MensagemAudio


- texto - imagem - audio

MensagemImagemTexto

PDS 2 - Programação Orientada a Objetos (Gerenciando Memória) 33 PDS 2 - Programação Orientada a Objetos (Gerenciando Memória) 34

Exercício Exercício

▪ Tarefas
MensagemBase
- data

▪ Faça as alterações necessárias no Makefile


- status
MensagemBase
+ exibir()

▪ Modifique Chat
- data
- status

MensagemImagem + exibir()
▪ Enviar MensagemImagemComTexto
▪ Alterar o Status das mensagens
- imagem

MensagemImagemComTexto
- msgImagem ▪ Como especializar Chat?
- msgTexto ▪ Conversa Individual / Grupo
▪ Verifique (corrija) a presença de memory leaks
MensagemImagemComTexto
- msgTexto
▪ Modifique para utilizar smart_pointers

PDS 2 - Programação Orientada a Objetos (Gerenciando Memória) 35 PDS 2 - Programação Orientada a Objetos (Gerenciando Memória) 36

Você também pode gostar