由于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
无论退出可执行代码块的原因(抛出异常,完成等),资源都会自动清理。