在C++中处理类间内存分配
Handling Inter Class Memory Deallocation in C++
我正在为我的机器学习课程用C++实现人工神经网络。这是我的"神经元"代码-
struct Neuron
{
float *inputs; // pointer to inputs array
int inputCount; // number of input
float *weights;
float sum; // linear weight sum of inputs
float output = 0.0; // output from activation function
float bias = 1.0;
float delta; // error gradient
Neuron(){}
Neuron(int inputCount)
{
this->inputCount = inputCount;
this->weights = new float [inputCount];
InitializeWeights();
}
float ActivationFunction(float x)
{
return 1.0 / (1.0 + exp(-x));
}
void Calculate(float *inputs)
{
this->inputs = inputs;
float temp = 0.0;
for(int i=0; i<inputCount; i++)
{
temp += weights[i] * inputs[i];
}
temp += bias;
sum = temp;
output = ActivationFunction(sum);
}
void InitializeWeights()
{
for(int i=0; i<inputCount; i++)
{
weights[i] = rand() % 101 / 100;
}
}
~Neuron()
{
delete[] weights;
}
};
我还有另一个名为"Layer"的结构,它表示一个层。神经元在那里被初始化为-
for(int i=0; i<neuronCount; i++)
{
neurons[i] = Neuron(inputCount);
}
其中"neuronCount"是该层中神经元的数量。问题是,由于析构函数调用,神经元中的权重数组立即被解除分配。我该怎么做才能防止这种情况发生?更重要的是,有没有更好的方法来设计我的程序?
您的代码有几个问题。
第一个原因是未能在默认构造函数中初始化input
和weights
指针。因此,以下简单程序将导致问题:
int main()
{
Neuron n;
}
由于n
的析构函数将试图在未初始化的指针weights
上调用delete []
。
另一个问题是Neuron
类不能安全地复制或分配。以下程序还将显示内存泄漏和双重删除错误的问题:
int main()
{
Neuron n(10);
Neuron n2 = n; // copy constructor
Neuron n3(2);
n = n3; // assignment
} // memory leaks, double deletion issues once main() exits.
第三个问题是,在Calculate
函数中传递一个指向float
的指针,但您不知道该指针在该函数内部是否有效,甚至不知道inputs
指针代表了多少项。如果这个数字小于weights
的数字,那么一旦i
超出input
的范围,您的代码就会出现内存溢出,试图访问inputs[i]
。
要解决这些问题,最简单的方法是使用std::vector
:
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstdlib>
struct Neuron
{
std::vector<float> inputs; // pointer to inputs array
std::vector<float> weights;
float sum = 0; // linear weight sum of inputs
float output = 0.0; // output from activation function
float bias = 1.0;
float delta = 0; // error gradient
Neuron() {}
Neuron(int inputCount) : weights(inputCount)
{
InitializeWeights();
}
float ActivationFunction(float x)
{
return 1.0 / (1.0 + exp(-x));
}
void Calculate(const std::vector<float>& inputs_)
{
inputs = inputs_;
// make sure vectors are the same size. If inputs is smaller,
// the new elements added will be 0
inputs.resize(weights.size());
// use inner_product to get the sum of the products.
sum = std::inner_product(std::begin(weights),
std::end(weights),
std::begin(inputs), 0.0f) + bias;
output = ActivationFunction(sum);
}
void InitializeWeights()
{
std::generate(std::begin(weights), std::end(weights), rand() % 101 / 100);
}
};
请注意,我们不再使用指针,因为std::vector
负责内存管理。我们也不需要有跟踪计数的成员变量(如inputCount
),因为向量通过使用vector::size()
知道自己的大小。
此外,std::inner_product用于在Calculate
函数中生成和(在将input
向量调整为与weights
相同的大小之后)。inputs_
作为std::vector
传递给Calculate
,因此您可以使用大括号初始化列表来调用它:
someInstance.Calculate({9.8, 5.6, 4.5}); // calls Calculate with a vector consisting of 3 items.
此外,InitializeWeights
函数调用std::generate算法函数来设置weights
矢量。
如果不使用std::vector
,那么您的类将需要一个复制构造函数和赋值运算符,遵循规则3。我不会讨论在不使用vector
的情况下如何修复类,因为答案会涉及更多内容。
最后一项是C++中rand()
的使用应替换为C++11随机数设施的使用。
- Win32编译器选项和内存分配
- 多个文件的内存分配错误"在抛出 'std :: bad_alloc' what (): std :: bad_alloc 的实例后终止调用" [C++]
- 当需要超过16GB的连续内存时,内存分配失败
- 尝试摆脱任何堆内存分配
- 以下代码执行哪种内存分配(动态或静态)?
- 开放 CV 中的动态内存分配,用于视频处理
- 为什么类和 main() 函数中也有动态内存分配
- 使用 NTAllocateVirtualMemory 和 GetProcAddress 的内存分配问题不起作用
- C++:矢量分配器行为、内存分配和智能指针
- 介于 [固定数组] 和 [带内存分配的指针] 之间的性能
- Linux C++ 中的页面对齐内存分配
- 整数内存分配/释放
- 将内存分配返回值强制转换为 TYPE 数组
- C++程序什么都不做,但瓦尔格林德显示内存分配
- 给定特定内存地址的数组的动态内存分配
- 如何完成内存分配
- 我刚刚了解了C++中的动态内存分配
- 在先前调用 string::find 后添加内存分配和内存集会导致它返回 npos.为什么?
- 对于堆上的页面对齐内存分配是否有任何优化或不同的 API?
- 无法删除布尔动态内存分配