调用对象内部和外部对象的函数的不同行为

时间:2019-02-03 00:57:10

标签: c++ c++11

我的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 

}

1 个答案:

答案 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();
}

请注意,使用智能指针而不是原始指针会更好。否则,您的程序将继续有遇到更多与内存相关的问题的风险。