简体   繁体   English

c ++ operator =工作很奇怪(在函数内部输出ok,但返回后错误..)

[英]c++ operator = working weird (output ok inside the function, but wrong after return..)

I have a program that I've been modifying to extract some data. 我有一个程序,我一直在修改以提取一些数据。
Recently I did another data extraction and used a work-around for lack of time. 最近我做了另一个数据提取,并使用了解决方案,因为时间不够。
Now, I am trying to find what the problem was, because I have some spare time. 现在,我试图找出问题所在,因为我有一些空余时间。

Below, there is a function Act() which is a member function of class Mat, and it forms a new matrix with altered data values. 下面是一个函数Act(),它是Mat类的成员函数,它形成一个具有改变数据值的新矩阵。 The Mat has a pointer to a buffer containing actual data. Mat有一个指向包含实际数据的缓冲区的指针。 I found that after the Act() function which returns a Matrix, the 'operator =' function is called. 我发现在返回Matrix的Act()函数之后,调用'operator ='函数。 (there was no 'operator =' function so I added it. maybe default '= operator' was being used. With or without my added 'operator =' function, it does not produce the final right output) Here is the portion of the '=' operator which is returning the data(type Mat).(it is a c++ code but I just used printf because it works anyway) (没有'operator ='函数所以我添加了它。也许默认'=运算符'正在被使用。无论有没有添加'operator ='函数,它都不会产生最终正确的输出。这是部分的返回数据的'='运算符(类型为Mat)。(它是一个c ++代码,但我只使用了printf,因为它无论如何都有效)

template<typename T>
Mat<T> Mat<T>::operator = (const Mat<T>& rhs)
{
  Mat<T> result(rhs.row_, rhs.col_);
  int num_bytes = sizeof(T) * rhs.row_ * rhs.col_;
  printf("ope = , res val = %x, src val = %x, row = %d, col = %d\n", result.val_, rhs.val_, rhs.row_, rhs.col_);
  for(int i=0;i<10;i++){
    printf("%04x ",((half_float::half *)rhs.val_)[i].data_);
    }
  printf("\n");
  memcpy(result.val_, rhs.val_, num_bytes);
  for(int i=0;i<10;i++){
    printf("%04x ",((half_float::half *)result.val_)[i].data_);
    }
  printf("\n");
  return result;
}

ope = , res val = 12199b0, src val = c07680, row = 128, col = 128 ope =,res val = 12199b0,src val = c07680,row = 128,col = 128
3be0 bbfc bbf5 3bf8 3af0 bbf6 bbef b29f bbaf 3bfd 3be0 bbfc bbf5 3bf8 3af0 bbf6 bbef b29f bbaf 3bfd
3be0 bbfc bbf5 3bf8 3af0 bbf6 bbef b29f bbaf 3bfd 3be0 bbfc bbf5 3bf8 3af0 bbf6 bbef b29f bbaf 3bfd

This '3be0 bbfc bbf5 ...' is the right pattern. 这个'3be0 bbfc bbf5 ......'是正确的模式。

The calling part looks like this. 调用部分看起来像这样。

  printf("calling activation..\n");
  d0_out = d0_out.Act(NN_CELL::AT_TANH);
  std::cout << "MLP Layer 0 executed." << std::endl;
  for(int i=0;i<10;i++){
    printf("%04x ",((half_float::half *)d0_out.val_)[i].data_);
    }
  printf("\n");

But after the assignment, seen from the main function, the data is weird. 但是从主函数看,在赋值之后,数据很奇怪。

MLP Layer 0 executed. MLP第0层已执行。
40de c2e2 c1eb 425e 3d4a c21b c187 b2b8 bfce 4358 40de c2e2 c1eb 425e 3d4a c21b c187 b2b8 bfce 4358

As you can see, the data is wrong. 如您所见,数据是错误的。
The only way I can produce right output is using a new object and assigning the result of Act() function to it. 我能产生正确输出的唯一方法是使用一个新对象并将Act()函数的结果赋给它。

NN_CELL::Mat<T> d0_out1 = d0_out.Act(NN_CELL::AT_TANH); // tmp work-around  

Then, d0_out1 (new object) contains the right data(3be0 bbfc bbf5 ..), instead of original 然后,d0_out1(新对象)包含正确的数据(3be0 bbfc bbf5 ..),而不是原始数据

d0_out = d0_out.Act(NN_CELL::AT_TANH);   

What is wrong with the original code? 原始代码有什么问题?

operator= should modify *this, not create a new temporal object X, copy the received data to X and then return X. You have created a temporal object but the data of the class that runs operator= has not been modified! operator =应该修改* this,而不是创建一个新的临时对象X,将接收到的数据复制到X然后返回X.你已经创建了一个临时对象,但是运行operator =的类的数据还没有被修改!

Try this code: 试试这段代码:

template<typename T>
Mat<T> Mat<T>::operator = (const Mat<T>& rhs)
{
  int num_bytes = sizeof(T) * rhs.row_ * rhs.col_;
  printf("ope = , res val = %x, src val = %x, row = %d, col = %d\n", this->val_, rhs.val_, rhs.row_, rhs.col_);
  for(int i=0;i<10;i++){
    printf("%04x ",((half_float::half *)rhs.val_)[i].data_);
    }
  printf("\n");
  memcpy(this->val_, rhs.val_, num_bytes);
  for(int i=0;i<10;i++){
    printf("%04x ",((half_float::half *)this->val_)[i].data_);
    }
  printf("\n");
  return *this;
}

a = a.Act() does not work, because you have implemented operator= incorrectly. a = a.Act()不起作用,因为你已经错误地实现了operator= The default operator= does not work in this case because you have a pointer in your class, and when the temporary returned by Act() is destroyed, it probably invalidates the pointer. 默认operator=在这种情况下不起作用,因为您的类中有一个指针,并且当Act()返回的临时值被销毁时,它可能使指针无效。

operator= is called, because you wrote = in your code. operator=被调用,因为你在代码中写了= When you use "tmp work-around", you create a new object, which does not call operator= but the copy constructor. 当您使用“tmp work-around”时,您将创建一个新对象,该对象不会调用operator=而是复制构造函数。 This seems to work. 这似乎有效。

As for how to implement operator= correctly: Assignment operator should modify the existing object, instead of returning a new one. 至于如何正确实现operator= :赋值运算符应修改现有对象,而不是返回新对象。

For example: 例如:

struct A {
    int row_, col_;
    float *val_;

    A& operator=(const A& rhs) {
        if (this != &rhs) {
            const int num_bytes = sizeof(float) * rhs.row_ * rhs.col_;
            row_ = rhs.row_;
            col_ = rhs.col_;
            memcpy(val_, rhs.val_, num_bytes);
        }
        return *this;
    }
};

As the comments state correctly, the Assignment Operator is intended to modify an already existing object. 当注释正确陈述时, 赋值运算符旨在修改已存在的对象。 You're creating a new one and returning that. 你正在创建一个新的并返回它。

Try something like this: 尝试这样的事情:

template<typename T>
Mat<T>& Mat<T>::operator = (const Mat<T>& rhs)
{
  row_ = rhs.row_;
  col_ = rhs.col_;
  delete val_;
  val_ = new T[row_*col_];

  int num_bytes = sizeof(T) * rhs.row_ * rhs.col_;
  printf("ope = , res val = %x, src val = %x, row = %d, col = %d\n", val_, rhs.val_, rhs.row_, rhs.col_);
  for(int i=0;i<10;i++){
    printf("%04x ",((half_float::half *)rhs.val_)[i].data_);
    }
  printf("\n");
  memcpy(val_, rhs.val_, num_bytes);
  for(int i=0;i<10;i++){
    printf("%04x ",((half_float::half *)val_)[i].data_);
    }
  printf("\n");
  return *this;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM