c++运算符=工作异常(函数内部输出正常,但返回后错误)
c++ operator = working weird (output ok inside the function, but wrong after return..)
我有一个程序,我一直在修改它来提取一些数据
最近我又进行了一次数据提取,由于时间不够,我使用了变通方法
现在,我正试图找出问题出在哪里,因为我有一些空闲时间。
下面有一个函数Act(),它是类Mat的成员函数,它用更改的数据值形成了一个新的矩阵。Mat有一个指向包含实际数据的缓冲区的指针。我发现在返回矩阵的Act()函数之后,会调用"operator="函数。(没有"operator="函数,所以我添加了它。可能使用了默认的"=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 = %dn", 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,行=128,列=128
3be0 bbfc bbf5 3bf8 3af0 bbf6 bbef b29f bbaf 3bfd
3 be0 bbfcbbf5 3 bf8 3af 0 bbf6 bbef b29 f bbaf 3 bfd
这个"3be0 bbfc bbf5…"是正确的模式。
调用部分看起来是这样的。
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");
但在赋值之后,从主函数中可以看出,数据很奇怪(在=运算符内部,复制似乎是正确的,但在外部,它不是)。
MLP层0已执行
40de c2e2 c1eb 425e 3d4a c21b c187 b2b8 bfce 4358
正如你所看到的,数据是错误的
我能产生正确输出的唯一方法是使用一个新对象并将Act()函数的结果分配给它。
NN_CELL::Mat<T> d0_out1 = d0_out.Act(NN_CELL::AT_TANH); // tmp work-around
然后,d0_out1(新对象)包含正确的数据(3be0 bbfc bbf5..),而不是原始
d0_out = d0_out.Act(NN_CELL::AT_TANH);
原始代码出了什么问题?
a = a.Act()
不起作用,因为您错误地实现了operator=
。默认的operator=
在这种情况下不起作用,因为类中有一个指针,当Act()
返回的临时指针被销毁时,它可能会使指针无效。
调用operator=
,因为您在代码中编写了=
。当您使用"tmp解决方案"时,您将创建一个新对象,该对象不调用operator=
,而是调用复制构造函数。这似乎奏效了。
至于如何正确实现operator=
:赋值运算符应该修改现有对象,而不是返回新对象。
例如:
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;
}
};
operator=应该修改*this,而不是创建一个新的时态对象X,将接收到的数据复制到X,然后返回X。您已经创建了一个时态对象,但运行operator=的类的数据尚未修改!
试试这个代码:
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 = %dn", 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;
}
由于注释状态正确,Assignment Operator用于修改已存在的对象。你正在创建一个新的并返回。
试试这样的东西:
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 = %dn", 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;
}
- (C++)分析树以计算返回错误值的简单算术表达式
- glad 导致 glfwSwapBuffers 返回错误消息
- 我的模板类方法返回错误类型?
- 共享内存:MapViewOfFile 返回错误 5
- 使用 std::forward_list 返回错误的队列实现
- FFMPEG:sws_scale返回错误:切片参数 0, 2160 无效
- __int64 CString 返回错误的值 - C++ MFC
- C++ OpenGL 中,绘制形状返回错误
- Python os.system() 返回错误值
- 函数从指针 c++ 中获取错误的值并返回错误的答案
- LibClang clang_getArgType() 返回错误的类型
- 除法函数返回错误的值
- 当命令失败时,gzip 会在 C++ 中返回错误代码吗?
- 矩阵逆变器返回错误的反转
- openCL-创建子缓冲区返回错误代码13
- Qt SQL LIKE语句返回错误
- GetLastError()从FtpPutFile()返回错误6
- PfCreateInterface返回错误120(未实现)
- 为什么 Pa_GetStreamTime() 返回错误?
- G++ 在尝试使用 G++ 使用 openCV 进行编译后返回错误