对象在C++中作为参数传递给函数时被修改
Objects modified when they are passed to a function as arguments in C++
我有以下简单的向量类,其中我可以定义不同大小的向量并将它们求和;我重载了+运算符,并包含了一个简单的数据显示方法deslegar();该类定义为:
class Cvector{
private:
int dim;
float * C;
public:
Cvector(){};
Cvector(int n){dim=n; C = new float[dim];};
~Cvector(){delete [] C;};
int getdim(){return dim;};
float getC(int i){
if(i<dim && i>=0)
return C[i];
else
return 0;
};
void setC(int i, float x){
if(i<dim && i>=0)
C[i]=x;
}
void desplegar(){
cout<<"[ ";
for(int i=0;i<dim;i++)
cout<<getC(i)<<" ";
cout<<" ]"<<endl;
}
Cvector operator + (Cvector);
};
Cvector Cvector::operator + (Cvector A){
int n;
if(A.getdim()>dim)
n=A.getdim();
else
n=dim;
Cvector temp(n);
for(int i=0;i<n;i++)
temp.setC(i,getC(i)+A.getC(i));
return temp;
}
当我运行以下代码时,一切都很好:
Cvector X(2);
Cvector Y(3);
定义维度2和3 的对象
X.setC(0,1);
X.setC(1,4);
Y.setC(0,0);
Y.setC(1,6);
Y.setC(2,9);
将相应的值添加到每个维度(X为2,Y为3)
X.desplegar();
Y.desplegar();
Cvector T=Y+X;
T.desplegar();
所有的东西都显示正确,直到这里,T显示向量Y和向量X的和,这就是我想要的。但当我运行时
X.desplegar();
它只显示来自内存的无关数据,当对象X作为参数传递给运算符+时,它似乎被修改了,为什么会这样?如果我使用指向对象的指针,这不会发生,但发生这种情况似乎并不直观。
有人能评论吗?
当用参数pass-by-value重载operator +
时,会调用复制构造函数来实例化临时对象。默认情况下,副本构造函数是原始对象的逐位副本。就在该方法返回之前,在临时对象上调用用户定义的析构函数,在该对象中释放底层存储。
若要更正代码,请自行定义复制构造函数或通过引用传递参数。
请永远记住三条规则,即当你定义了析构函数、复制构造函数和赋值运算符中的任何一个时,请考虑定义这三个函数中的其他函数。
问题出在operator+
中。
Cvector Cvector::operator + (Cvector A)
在这里,您通过对第二个操作数(在您的情况下是X
)进行复制来传递它。这个复制(A
)将使它的C
指针指向与X
向量相同的内存:
Cvector T=Y+X;
在operator+
结束时,副本将被销毁,析构函数将被调用,内存将被释放。由于此内存由X
的副本和X
本身共享,因此您将拥有垃圾。更改您的operator+
,使其成为参考,一切都会正常工作:
Cvector Cvector::operator + ( const Cvector & A )
请注意,实现复制构造函数也是一个好主意。
您复制矢量不正确temp在运算符+结束时自动调用其析构函数,导致T有一个悬空指针。你可能正在做类似于X的事情,如果不看完整的程序,很难判断。
Cvector没有复制构造函数,因此将生成默认构造函数:
Cvector::Cvector(Cvector const & original)
: dim(original.dim), C(original.C)
{}
这将执行浅复制,也就是说,您现在有两个具有相同C指针的对象。
因此,当您将X作为参数复制到任何函数时,都会发生以下情况:
Cvector x;
// populate X
// now call this:
void foo(Cvector y) { // y is created as a copy of x
} // y is destroyed
当复制的参数被销毁时,它会删除与原始参数共享的C。
应进行以下更改:
- 适当编写一个副本构造函数和赋值运算符,用于执行深度复制(这将阻止副本在销毁时破坏原始对象)
- 在不更改参数时通过const引用传递参数
- 修改函数中的指针(将另一个指针作为参数传递)
- 如何从子成员函数修改父公共成员变量
- 为什么在我的函数类型后使用引用运算符 (&) 允许我修改它返回的值?
- C++ 使用同一函数时如何修改间距
- C++:通过函数修改数组
- 如何调试指针参数是否通过函数修改
- 为什么我可以在C 11中使用const函数修改类
- Qt - 使用λ函数修改先前连接信号的插槽参数
- 如何返回通过memcpy函数修改的两个阵列
- Arduino esp8266中的c++函数修改了c文件中生成的浮点值,在c++函数退出后,c文件中会出现胡言乱语
- 调用带有扭曲的库函数-修改其某些行为
- 二维数组被函数修改后如何删除
- 由算术运算符成员函数修改的动态数组的复制构造函数
- 如何在函数修改堆栈时将堆栈传递给函数
- 当我们可以使用普通函数修改静态数据成员时,静态成员函数的需求是什么?
- 通过函数修改数组的元素
- 挂钩(热补丁)类成员函数.修改虚函数表项
- 为什么引用成员可以被const成员函数修改
- 使用 friend 关键字和使用成员函数修改类内部的私有变量有什么区别
- c++通过一个函数修改多个数组