我的C ++代码正在发生一些非常奇怪的行为。我在MultiplyOperation类中有一个向后函数,该函数是从另一个对象FloatTensor类调用的,该对象具有该MultiplyOperation类的实例。
如果我分别调用three.backOperation->backward(1);
和three.backOperation->backward(1);
,则输出结果将有所不同,但应该相同。请帮忙。
这是我的代码:
#include<iostream>
using namespace std;
class FloatTensor;
class MultiplyOperation{
public:
FloatTensor *t1, *t2;
float grad = 10;
MultiplyOperation(FloatTensor* t1, FloatTensor* t2);
FloatTensor compute();
void backward(float gradient);
};
class FloatTensor {
public:
float val;
float grad;
MultiplyOperation* backOperation = NULL, *frontOperation = NULL;
FloatTensor() {
// default
}
FloatTensor(float value) {
this->val = value;
this->backOperation = NULL;
}
FloatTensor(float value, MultiplyOperation* backOp) {
this->val = value;
this->backOperation = backOp;
}
void backward(float gradient) {
this->backOperation->backward(gradient);
}
FloatTensor operator * (FloatTensor two) {
MultiplyOperation ope(this,&two);
this->frontOperation = &ope;
return this->frontOperation->compute();
}
};
MultiplyOperation::MultiplyOperation(FloatTensor* te1, FloatTensor* te2) {
this->t1 = te1;
this->t2 = te2;
}
FloatTensor MultiplyOperation::compute() {
return FloatTensor(this->t1->val*this->t2->val, this);
}
void MultiplyOperation::backward(float gradient) {
cout<<this->t2->val<<endl;
}
int main() {
FloatTensor one(2);
FloatTensor two(4);
FloatTensor three = one*two;
three.backOperation->backward(1); // should be same as output of next line and is 4. (which is correct)
three.backward(1); // should be same as output of above line but is garbage value -4.12131
}
答案 0 :(得分:2)
由于以下功能,您的程序具有未定义的行为:
FloatTensor operator * (FloatTensor two) {
MultiplyOperation ope(this,&two);
this->frontOperation = &ope;
return this->frontOperation->compute();
}
您正在存储一个指向对象ope
的指针,该对象一旦函数返回就不再有效。
在创建two
时使用ope
存在相同的问题。
您可以更改函数以存储指向动态分配对象的指针以解决该问题。
FloatTensor operator * (FloatTensor two) {
this->frontOperation = new MultiplyOperation(this, new FloatTensor(two));
return this->frontOperation->compute();
}
或使用
FloatTensor operator * (FloatTensor& two) {
this->frontOperation = new MultiplyOperation(this, &two);
return this->frontOperation->compute();
}
请注意,使用智能指针而不是原始指针会更好。否则,您的程序将继续有遇到更多与内存相关的问题的风险。