Ajude nosso projeto a se manter online.

Alocação dinâmica de objetos com ponteiros: O operador new e delete

 Neste tutorial de nosso Curso de Orientação a Objetos em C++, vamos aprender a usar ponteiros com objetos, e ver uma nova maneira de alocar memória.


Ponteiros de Objetos

Inicialmente, vamos criar um classe, chamada Student, que vai ter duas variáveis (math e english), que vai armazenar as notas do aluno. Também vai ter a get and set, e uma chamada getAverage() para calcular a média de cada aluno.

Nossa classe, toda completinha e bonitinha fica assim:

class Student
{
    private:
        double math, english;

    public:
        double getAverage() const;
        void setMath(double);
        void setEnglish(double);
        double getMath() const;
        double getEnglish() const;
};

double Student::getAverage() const
{
    return (getMath() + getEnglish())/2;
}

void Student::setMath(double m)
{
    math = m;
}
void Student::setEnglish(double e)
{
    english = e;
}
double Student::getMath() const
{
    return math;
}
double Student::getEnglish() const
{
    return english;
}

Vamos agora declarar um ponteiro de nome 'ptr' do tipo Student:

  • Student *ptrStudent
Agora vamos declarar de fato um objeto da classe Student:
  • Student s1;
Podemos associar o ponteiro com o objeto da seguinte maneira:
  • ptrStudent = &s1
    (não esqueça o &, lembre-se que ponteiros armazenam endereços de memória, e ao colocarmos o & antes de uma variável, ele fornece o endereço daquela variável)

Trabalhando com ponteiros com Classes e Objetos: ->

Como já estudando ponteiros, vimos que eles podem fazer mil maravilhas.
Pode exemplo, no exemplo anterior, para o ponteiro acessar os elementos de um objeto, devemos usar o operador ->

Vamos definir duas notas para um aluno:

ptrStudent->setMath(8);
ptrStudent->setEnglish(10);

E para sabermos a média, usando ponteiro, basta fazer:
ptrStudent->getAverage()

Nosso código completo fica:
#include <iostream>
using namespace std;

class Student
{
    private:
        double math, english;

    public:
        double getAverage() const;
        void setMath(double);
        void setEnglish(double);
        double getMath() const;
        double getEnglish() const;
};

double Student::getAverage() const
{
    return (getMath() + getEnglish())/2;
}

void Student::setMath(double m)
{
    math = m;
}
void Student::setEnglish(double e)
{
    english = e;
}
double Student::getMath() const
{
    return math;
}
double Student::getEnglish() const
{
    return english;
}

int main()
{
    Student *ptrStudent;
    Student s1;

    ptrStudent = &s1;
    
    ptrStudent->setMath(8);
    ptrStudent->setEnglish(10);

    cout << ptrStudent->getAverage()<<endl;

    return 0;
}
Note que usamos apenas um aluno, poderíamos ter criado mil alunos e ir fazendo o ponteiro apontar para cada um desses alunos, e o código seria sempre o mesmo, por exemplo:
Student s1, s2, s3, s4;

Faz: ptrStudent = &s1
Depois: ptrStudent = &s2
Depois: ptrStudent = &s3
Depois ptrStudent = &s4

E prontinho, depois é só usr
ptrStudent->setMath();
ptrStudent->setEnglish();
ptrStudent->getAverage()

Isso evita muito escrever código à toa.

Alocando espaço para objetos: Operador new

Existe uma nova maneira de instanciar objetos, é a partir do operador new.
Primeiro você declara seu ponteiro:
  • MyClasse *ptr;
Nesse ponto, temos um ponteiro que serve para apontar para um objeto? Que objeto é esse? Vamos criar ele agora, da seguinte maneira:
  • ptr = new MyClasse

Deletando objetos - delete

Quando criamos um objeto, via instanciamento normal, ele vai sempre existir e ocupar um espaço na memória. Uma das vantagens de fazer a alocação dinâmica de memória, através do new, é que podemos destruir esse ponteiro, destruindo esse objeto e liberando espaço na memória, para isto, basta usar o operador delete:
  • delete ptr;

E prontinho, temos um espaço livro na máquina. Isso pode parecer bobeira agora, mas quando você criar sistemas super complexos que exigem o máximo de eficiência e o menor uso possível de memória (como para programar um relógio de pulso ou microondas, que tem pouca memória), é uma técnica importantíssima.

Veja o código abaixo, apenas com um ponteiro, preenchemos a nota de dois alunos e calculamos sua média, e tudo isso apenas como um objeto/ponteiro da classe Student. Veja como ficou o código:

#include <iostream>
using namespace std;

class Student
{
    private:
        double math, english;

    public:
        double getAverage() const;
        void setMath(double);
        void setEnglish(double);
        double getMath() const;
        double getEnglish() const;
};

double Student::getAverage() const
{
    return (getMath() + getEnglish())/2;
}

void Student::setMath(double m)
{
    math = m;
}
void Student::setEnglish(double e)
{
    english = e;
}
double Student::getMath() const
{
    return math;
}
double Student::getEnglish() const
{
    return english;
}

int main()
{
    Student *ptrStudent;
    ptrStudent = new Student;

    ptrStudent->setMath(8);
    ptrStudent->setEnglish(10);
    cout << "Media do Estudante 1: " <<ptrStudent->getAverage()<<endl;

    ptrStudent->setMath(6);
    ptrStudent->setEnglish(7);
    cout << "Media do Estudante 2: " <<ptrStudent->getAverage()<<endl;

    delete ptrStudent;

    return 0;
}

Nenhum comentário:

Postar um comentário