Поскольку требуется вызвать fann_destroy_train_data
, вы можете использовать C ++ и RAII, используя следующую оболочку:
struct fann_wrapper
{
fann_train_data *td;
fann_wrapper(fann_train_data* p) : td(p) {}
~fann_wrapper() { fann_destroy_train_data(td); }
};
//...
for (int i = 1; i <= epochs; ++i) {
for (std::vector<std::filesystem::path>::iterator it = batchFiles.begin(); it != batchFiles.end(); ++it) {
struct fann_train_data *data = fann_read_train_from_file(it->string().c_str());
// the next line ensures that fann_destroy_train_data is called
fann_wrapper fw(data);
fann_shuffle_train_data(data);
float error = fann_train_epoch(ann, data);
} // when this curly brace is encountered, the fann_destroy_train_data is always called
}
fann_wrapper
просто содержит указатель fain_train_data
, и при уничтоженииfann_wrapper
, fann_train_data
уничтожено.
Причина, по которой этот метод намного безопаснее, чем необработанный метод C
, заключается в том, что может быть выдано возможное исключение (по любой причине).Если выдается исключение, то fann_train_data
будет всегда уничтожаться при использовании fann_wrapper
.Эту гарантию нельзя сделать с помощью метода C
, поскольку исключение будет полностью пропущено по любой строке, которая имеет fann_destroy_train_data
.
Пример:
for (int i = 1; i <= epochs; ++i) {
for (std::vector<std::filesystem::path>::iterator it = batchFiles.begin(); it != batchFiles.end(); ++it) {
struct fann_train_data *data = fann_read_train_from_file(it->string().c_str());
fann_shuffle_train_data(data);
float error = fann_train_epoch(ann, data);
fann_destroy_train_data(data); // this line is not executed if an exception is thrown above, thus a memory leak
}
}
Именно поэтому RAII являетсяважная концепция в C ++.Ресурсы будут очищаться автоматически, независимо от причины, по которой завершается исполняемый блок кода (генерируется исключение, выполняется return
и т. Д.).