我有一个奇怪的问题,我想知道 C ++ 11 是否有关于此的特殊规则,我不知道。
我有两节课:
1 - ClNeuron (摘要)
2 - ClLSTMNeuron ( ClNeuron的孩子)
声明如下:
class ClNeuron
{
protected:
//Initialization function
virtual void Init(unsigned long p_uid);
double Sigmoid(double p_value);
double SigmoidDerivative(double p_value);
double TanH(double p_value);
double TanHDerivative(double p_value);
public:
const double CONST_DEFAULT_MOMENTUM_VALUE = 0.1;
const double CONST_DEFAULT_LEARNING_RATE = 0.05;
//All of the output connection of this neuron
std::vector<ClNeuronConnection*> m_output_connections;
//Al of the input connection of this neuron
std::vector<ClNeuronConnection*> m_input_connections;
bool m_initialized;
double m_result_buffer;
//Error related informations
double m_last_error_delta;
double m_error_gradient;
unsigned long m_uid;
double m_learning_rate;
public:
bool m_is_bias;
ClDataSet* m_dataset;
virtual ~ClNeuron();
ClNeuron(unsigned long p_uid);
ClNeuron();
//Connect this neuron's output to another / others neurons' input
virtual bool AddOutputConnection(ClNeuron* p_neuron);
//This neuron got a request to have multiple new input
virtual std::vector<ClNeuronConnection*> InputConnectionRequest(ClNeuron* p_neuron);
//Tell the neuron to fire the sum of the processed inputs
virtual double Fire();
virtual double Fire(double p_data);
//void ComputeErrorGradient(double p_wanted_output);
//Function updating all of the current neuron's weight of the OUTPUT connections , depending on an error ratio
//void UpdateWeights();
//Set the result buffer using the transfer function . NOTE : This is a pure virtual function
virtual void ProcessInputs() = 0;
virtual bool ComputeErrorGradient() = 0;
virtual void ComputeWeightDeltas();
virtual void UpdateWeights();
virtual void ResetContext();
//Print neuron & connections & weights
virtual void PrintNeuronData();
};
class ClLSTMNeuron : public ClNeuron
{
protected:
std::vector<ClNeuronConnection*> m_forget_gate_input_connections;
std::vector<ClNeuronConnection*> m_input_gate_input_connections;
std::vector<ClNeuronConnection*> m_output_gate_input_connections;
double m_input_gate_result_buffer;
double m_output_gate_result_buffer;
double m_forget_gate_result_buffer;
double m_cell_state;
public:
//Override the ProcessInputs function
std::vector<ClNeuronConnection*> InputConnectionRequest(ClNeuron* p_neuron);
void ProcessInputs();
bool ComputeErrorGradient();
ClLSTMNeuron();
virtual ~ClLSTMNeuron();
};
问题如下: ClLSTMNeuron 构造函数调用它的父类函数 Init(),如下所示:
ClLSTMNeuron::ClLSTMNeuron()
{
ClNeuron::Init(0);
std::cout << "ClLSTMNeuron::ClLSTMNeuron() [" << this << "]: my OC [" << &this->m_output_connections << "] has a size of " << this->m_output_connections.size() << std::endl;
}
完成后,会给我以下输出:
ClLSTMNeuron::ClLSTMNeuron() [0000024BBC5720B8]: my OC [0000024BBC5720D0] has a size of 0
ClLSTMNeuron::ClLSTMNeuron() [0000024BBC5721D0]: my OC [0000024BBC5721E8] has a size of 0
ClLSTMNeuron::ClLSTMNeuron() [0000024BBC5722E8]: my OC [0000024BBC572300] has a size of 0
ClLSTMNeuron::ClLSTMNeuron() [0000024BBC572400]: my OC [0000024BBC572418] has a size of 0
ClLSTMNeuron::ClLSTMNeuron() [0000024BBC572518]: my OC [0000024BBC572530] has a size of 0
ClLSTMNeuron::ClLSTMNeuron() [0000024BBC572630]: my OC [0000024BBC572648] has a size of 0
ClLSTMNeuron::ClLSTMNeuron() [0000024BBC572748]: my OC [0000024BBC572760] has a size of 0
ClLSTMNeuron::ClLSTMNeuron() [0000024BBC572860]: my OC [0000024BBC572878] has a size of 0
在此输出中,我们可以清楚地看到每个 ClLSTMNeuron 实例的成员 m_output_connections 的地址。
但是,由于一个未知的原因,当我使用这样的动态分配实例化时:
this->m_neurons = new ClLSTMNeuron[p_number_of_neurons]();
if (this->m_neurons == NULL)
{
std::cout << "[Fatal Error] ClLSTMNeuronLayer::Init : Impossible to allocate " << p_number_of_neurons << " neurons in memory" << std::endl;
return false;
}
for (size_t i = 0; i < p_number_of_neurons; i++)
{
std::cout << "LSTM Neuron " << i << " is at [" << &this->m_neurons[i] << "] and it's OC [" << &this->m_neurons[i].m_output_connections << "] has size of " << this->m_neurons[i].m_output_connections.size() << std::endl;
}
我得到以下输出:
LSTM Neuron 0 is at [0000024BBC5720B8] and it's OC [0000024BBC5720D0] h size of 0
LSTM Neuron 1 is at [0000024BBC572150] and it's OC [0000024BBC572168] h size of 18446743758171348710
LSTM Neuron 2 is at [0000024BBC5721E8] and it's OC [0000024BBC572200] h size of 18446743758171348500
LSTM Neuron 3 is at [0000024BBC572280] and it's OC [0000024BBC572298] h size of 315538203026
LSTM Neuron 4 is at [0000024BBC572318] and it's OC [0000024BBC572330] h size of 17994617993471572384
LSTM Neuron 5 is at [0000024BBC5723B0] and it's OC [0000024BBC5723C8] h size of 0
LSTM Neuron 6 is at [0000024BBC572448] and it's OC [0000024BBC572460] h size of 17994617993471572409
LSTM Neuron 7 is at [0000024BBC5724E0] and it's OC [0000024BBC5724F8] h size of 0
我们可以清楚地看到神经元本身的地址&amp;成员 m_output_connections 的地址已更改:为什么会发生这种情况? 继承/多态中是否有任何概念,并且不知道?
我正在考虑典型的指针问题:索引不匹配,非初始化指针等... 但似乎找不到任何会引发这种行为的事情。
问题在Visual Studio 2015和GCC Linux中是不可复制的。
P.S 您可能会在此代码中看到错误,因为它不遵循非书面规则,例如: 始终使用虚拟析构函数或类似概念。 请随意让我知道我可能做的任何错误。
再次感谢您的时间!
答案 0 :(得分:0)
如果你有:
ClNeuron* m_neurons
一旦你重复它就会出现问题:
this->m_neurons = new ClLSTMNeuron[p_number_of_neurons]();
因为指针算术将考虑ClNeuron
而不是ClLSTMNeuron
进行偏移计算。
所以m_neurons[n]
是
*static_cast<ClNeuron*>(static_cast<char*>(m_neurons) + n * sizeof(ClNeuron))
而不是预期
*static_cast<ClLSTMNeuron*>(static_cast<char*>(m_neurons) + n * sizeof(ClLSTMNeuron))
答案 1 :(得分:-1)
如果我理解发生了什么以及你在问什么,地址改变的原因是:
(14.3) — new T[5] results in a call of operator new[](sizeof(T)*5+x)
其中x是数组初始化开销
因此new ClLSTMNeuron[p_number_of_neurons]();
不会在内存中的连续区域中生成p_number_of_neurons,它只是保留足够的内存来保存ClLSTMNeuron的p_number_of_neurons。
我不是c ++标准专家,但就我所知,这个过程就像新的[]新闻一样。然后它调用ClLSTMNeuron的构造函数,该构造函数分配并初始化ClLSTMNeuron值的内存并返回对该内存位置的const引用。然后将该内存移动到新的内存中。
或更简单地说,构造函数设置了一些内存,然后将其移入数组。所以这个的内存地址可能会也可能不会改变。
再次,我不是专家,其他人可以更正确地解释它。如果您想进行一些研究,请尝试阅读c ++ standard的第5.3.4节。