I'm deallocating objects created but I'm unsure whether my code is leaking memory or not I have a simple application which requires the user to input details about students and their grades. I have two different classes Student and Database. The Student class contains info about students, such as, their names and grades:

Student.h file:

#pragma once
#ifndef STUDENT_H
#define STUDENT_H
#include &lt;string&gt;

class Student {
private:
    std::string name;

public:
    Student(std::string name);

    const std::string getName() const;

    ~Student();
};

#endif // !STUDENT_H


Student.cpp file:

#include "student.h"
#include &lt;string&gt;
#include &lt;iostream&gt;

Student::Student(std::string name) {
    this-&gt;name = name;
}

const std::string Student::getName() const {
    return this-&gt;name;
}

Student::~Student() {
    std::cout &lt;&lt; "Student destructor\n";
}


Database.h file:

#pragma once
#ifndef DATABASE_H
#define DATABASE_H
#include &lt;string&gt;
#include "student.h"
#include &lt;vector&gt;

class StudentDatabase {
private:
    std::vector&lt;Student*&gt; student_list;

public:
    void add_student(Student* stud_obj);

    ~StudentDatabase();
};

#endif // !DATABASE_H


Database.cpp file:

#include "database.h"
#include "student.h"
#include &lt;string&gt;
#include &lt;iostream&gt;
#include &lt;vector&gt;

void StudentDatabase::add_student(Student* stud_obj) {
    std::cout &lt;&lt; "ADD STUDENT METHOD\n";
    StudentDatabase::student_list.push_back(stud_obj);
}

StudentDatabase::~StudentDatabase() {
    std::cout &lt;&lt; "Database destructor\n";

    std::vector&lt;Student*&gt;::iterator iter;

    for (iter = student_list.begin(); iter != student_list.end(); iter++) {
        delete* iter;
    }
}


Main.cpp file:

#include &lt;iostream&gt;
#include &lt;string&gt;
#include "database.h"
#include "student.h"

int main()
{
    std::string input;
    std::string name;

    StudentDatabase* database = new StudentDatabase();

    for (;;) {
        std::cout &lt;&lt; "0: Add student \n";

        std::cout &lt;&lt; "Enter a number (or q to quit) and press return... \n";

        std::cin &gt;&gt; input;
        std::cin.ignore();

        if (input == "q") {
            break;
        }

        else if (input == "0") {
            std::cout &lt;&lt; "Enter student's first name: ";
            std::getline(std::cin, name);

            Student* student_obj = new Student(name, surname, student_number, grade);
            database-&gt;add_student(student_obj);
        }
    }

    delete database;
    return 0;
}


My question is: am I correctly deallocating memory for Students from ~StudentDatabase()?

I know smart pointers are more appropriate but I want to make sure I understand raw pointers properly.
You don't need to use new everywhere. Inside your main function, the StudentDatabase could very well reside on the stack so you don't need to delete it yourself.

One of the issues with how StudentDatabase is written now is ownership semantics. Once a student pointer is added to the database, the database asumes ownership upon it and deletes it in the destructor. What if the same student pointer were to be added to multiple databases, or used after the database is deleted?

Smart pointers help prevent such errors.