Obawiam się, że ryzyko wycieków pamięci w tak napisanym programie jest dość znaczne.
Jak mogę zmodyfikować program, by takie ryzyko ograniczyć i jak upewnić się, że wycieków brak?
Jeżeli komuś chciałoby się rzucić okiem:
(chetnie wyslucham rowniez jakichkolwiek innych uwag dotyczacych kodu)
Student.h
#pragma once
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
using namespace std;
class CStudent;
ostream& operator<< (ostream& out, const CStudent& Student); //przeciazenie operatora wyjscia
fstream& operator<< (fstream& file, const CStudent& Student);
class CStudent
{
public:
CStudent();
~CStudent();
static void CreateStudents();
static void SetNrStudents(int nrStudents);
static void AddStudents(int addStudents = 1);
static void DeleteStudent(int deleteStudent);
static void Menu();
static void ShowDane();
static void SaveDane();
static void DeleteIt();
friend ostream& operator<< (ostream& out, const CStudent& Student); // zaprzyjaznienie przeciazonego operatora
friend fstream& operator<< (fstream& file, const CStudent& Student);
private:
void SetDane();
static vector <CStudent*> _students;
static int _nrStudents;
string _imie;
string _nazwisko;
int _nrAlbumu;
float _srednia;
string* _przedmioty;
int _nrPrzedmioty;
};
Student.cpp
#include "Student.h"
CStudent::CStudent()
{
cout << endl << "### KONSTRUKTOR" << endl; // Just for info
SetDane();
}
CStudent::~CStudent()
{
if (_przedmioty != NULL)
{
delete[] _przedmioty;
_przedmioty = NULL;
}
cout << endl << "--- DESTRUKT" << endl; // Just for info
}
void CStudent::SetNrStudents(int nrStudents)
{
_nrStudents = nrStudents;
}
void CStudent::Menu()
{
cout << endl << "MENU" << endl;
cout << "################" << endl;
cout << "0. Usun i zakoncz" << endl;
cout << "1. Dodaj Studenta" << endl;
cout << "2. Usun Studenta" << endl;
cout << "3. Pokaz Baze" << endl;
cout << "4. Zapisz do pliku" << endl;
}
void CStudent::CreateStudents()
{
for (int i = 0; i < _nrStudents; i++)
{
_students.push_back(new CStudent()); // Utworzenie nowego obiektu w "vektorze"
}
}
void CStudent::AddStudents(int addStudents)
{
for (int i = 0; i < addStudents; i++)
{
_students.push_back(new CStudent()); // Utworzenie nowego obiektu
}
_nrStudents += addStudents;
}
void CStudent::DeleteStudent(int deleteStudent)
{
delete *(CStudent::_students.begin() + deleteStudent); // Usuwanie obiektu
*(CStudent::_students.begin() + deleteStudent) = NULL; // "zerowanie" wskaznika
_students.erase(CStudent::_students.begin() + deleteStudent); // usuwanie elementu z "vektora"
_nrStudents--;
}
void CStudent::SetDane()
{
cout << endl << "Imie: " << endl;
cin >> _imie;
cout << endl << "Nazwisko: " << endl;
cin >> _nazwisko;
cout << endl << "Numer Albumu: " << endl;
cin >> _nrAlbumu;
cout << endl << "Srednia: " << endl;
cin >> _srednia;
cout << endl << "Podaj ilosc przedmiotow: " << endl;
cin >> _nrPrzedmioty;
_przedmioty = new string[_nrPrzedmioty]; // Dynamiczna alokacja
for (int i = 0; i < _nrPrzedmioty; i++)
{
cout << endl << "Nazwa przedmiotu nr: " << (i + 1) << " z " << _nrPrzedmioty << endl;
cin >> _przedmioty[i];
}
cout << endl << "Wczytano studenta z liczba przedmiotow: " << _nrPrzedmioty << endl;
}
void CStudent::ShowDane()
{
int c = 0;
vector<CStudent*>::iterator itr; // iterator do sprawnego poruszania sie po elementach vektora
for (itr = CStudent::_students.begin(); itr != CStudent::_students.end(); itr++)
{
cout << endl << "Student nr: " << c << endl;
cout << **itr;
c++;
}
}
void CStudent::SaveDane()
{
int c = 0;
fstream file("student.txt", ios::out);
vector<CStudent*>::iterator itr;
for (itr = CStudent::_students.begin(); itr != CStudent::_students.end(); itr++)
{
file << endl << "Student nr: " << c << endl;
file << **itr;
c++;
}
file.close();
}
void CStudent::DeleteIt() // Usuwanie dynamicznie zaalokowan pamiecie, czyszczenie vektora
{
vector<CStudent*>::iterator itr;
for (int i = 0; (CStudent::_students.begin() + i) != CStudent::_students.end(); i++)
{
CStudent::_students.begin();
delete *(CStudent::_students.begin() + i);
*(CStudent::_students.begin() + i) = NULL;
}
_students.clear();
}
vector <CStudent*> CStudent::_students; // inicjalizacja pola statyczneg0
int CStudent::_nrStudents = 0; // -||-
ostream& operator<< (ostream& out, const CStudent& Student)
{
out << "------------------" << endl;
out << Student._imie << endl << Student._nazwisko << endl << Student._nrAlbumu << endl << Student._srednia << endl;
out << "Przedmioty: " << endl;
for (int i = 0; i < Student._nrPrzedmioty; i++)
{
out << Student._przedmioty[i] << endl;
}
return out;
}
fstream& operator<< (fstream& file, const CStudent& Student)
{
file << "------------------" << endl;
file << Student._imie << endl << Student._nazwisko << endl << hex << Student._nrAlbumu << endl << Student._srednia << endl;
file << "Przedmioty: " << endl;
for (int i = 0; i < Student._nrPrzedmioty; i++)
{
file << Student._przedmioty[i] << endl;
}
return file;
}
main.cpp
#include "Student.h"
int main(void)
{
int choice;
int nrS;
cout << "Ilu studentow?" << endl;
cin >> nrS;
CStudent::SetNrStudents(nrS); // Utworzenie poczatkowo podanej ilosci studentow
CStudent::CreateStudents();
do
{
CStudent::Menu();
cin >> choice;
switch (choice)
{
case 1:
int ile;
cout << endl << "Ilu studentow dodac?" << endl;
cin >> ile;
CStudent::AddStudents(ile);
break;
case 2:
int ktory;
cout << endl << "Ktorego usunac?" << endl;
cin >> ktory;
CStudent::DeleteStudent(ktory);
break;
case 3:
CStudent::ShowDane();
break;
case 4:
CStudent::SaveDane();
break;
case 0:
CStudent::DeleteIt();
break;
}
} while (choice != 0);
return 0;
}
btw. istnieje opcja typu 'spojler' ? (w celu ukrycia przydługiego tekstu).