【发布时间】:2015-08-28 10:08:40
【问题描述】:
我在释放内存时遇到问题。首先我要展示我的构造函数、析构函数和类的私有部分:
第 1 类:
class VectorDinamico {
private:
int util, tam;
int *vect;
/*Rest of the class*/
}
VectorDinamico::VectorDinamico() {
util = 0;
tam = 10;
vect = new int[10];
}
VectorDinamico::VectorDinamico(const VectorDinamico &v){
vect = new int[v.tam];
for (int i = 0 ; i < v.util; i++) {
vect[i] = v.vect[i];
}
util = v.util;
tam = v.tam;
}
VectorDinamico::~VectorDinamico() {
delete []vect;
}
VectorDinamico& VectorDinamico::operator= (const VectorDinamico &v) {
if (this != &v) {
delete []vect;
vect = new int[v.tam];
for (int i = 0 ; i < v.util; i++) {
vect[i] = v.vect[i];
}
util = v.util;
tam = v.tam;
}
return *this;
}
工作正常(Valgrind:退出时没有使用任何东西)
第 2 类:
class Conjunto {
private:
VectorDinamico datos;
/*Rest of the class*/
}
//Is empty because it uses the VectorDinamico constructor( I think )
Conjunto::Conjunto() {}
Conjunto::Conjunto( const Conjunto &c) {
datos = c.datos; // = Is overloaded in VectorDinamico
}
//Is empty because it uses the VectorDinamico destructor( I think )
Conjunto::~Conjunto() {};
Conjunto& Conjunto::operator=( const Conjunto &c) {
if (this != &c)
datos = c.datos;
return *this;
}
工作正常(Valgrind:退出时没有使用任何东西)
第 3 课:(我认为这是问题所在)
class SetConjuntos{
private:
Conjunto *conjuntos;
int util, tam;
/*Rest of the class*/
}
SetConjuntos::SetConjuntos(){
util = 0;
tam = 10;
conjuntos = new Conjunto[10];
}
SetConjuntos::SetConjuntos(const SetConjuntos &sc){
util = sc.util;
tam = sc.tam;
conjuntos = new Conjunto[tam];
for(int i = 0 ; i < util ; i++)
conjuntos[i]=sc.conjuntos[i];
}
//Here is my problem ( I think )
//anyway I've left it empty, because I think it uses the Conjunto destructor's
SetConjuntos::~SetConjuntos(){
//delete []conjuntos; ( Cause segmetation fault )
}
我认为 SetConjuntos 析构函数不正确,因为 Valgrind 输出是:
==6838== LEAK SUMMARY:
==6838== definitely lost: 2,912 bytes in 4 blocks
==6838== indirectly lost: 11,320 bytes in 180 blocks
SetConjuntos 的析构函数必须是怎样的?
谢谢
------------解决了将 operator= 添加到 SetConjuntos----------------
我没有实现赋值运算符,因为他认为如果他不显式使用是没有必要的。我错了。
现在第 3 课是:
class SetConjuntos{
private:
Conjunto *conjuntos;
int util, tam;
/*Rest of the class*/
}
SetConjuntos::SetConjuntos(){
util = 0;
tam = 10;
conjuntos = new Conjunto[10];
}
SetConjuntos::SetConjuntos(const SetConjuntos &sc){
util = sc.util;
tam = sc.tam;
conjuntos = new Conjunto[tam];
for(int i = 0 ; i < util ; i++)
conjuntos[i]=sc.conjuntos[i];
}
SetConjuntos::~SetConjuntos(){
delete []conjuntos; //( NO cause segmetation fault )
}
SetConjuntos& SetConjuntos::operator=(const SetConjuntos &sc){
if(this != &sc){
util = sc.util;
tam = sc.tam;
Conjunto *conjuntos_loc = new Conjunto[tam];
for(int i = 0 ; i < util ; i++)
conjuntos_loc[i]=sc.conjuntos[i];
delete[] conjuntos;
conjuntos = conjuntos_loc;
}
return *this;
}
【问题讨论】:
-
你有复制构造函数吗?
-
“它使用 xxx 构造函数/析构函数”不好说。它调用所有数据成员的构造函数(分别是析构函数)(如果它们有,我的意思是——如果它们不是原始类型)。
VectorDinamico的构造函数和析构函数都可以。Conjunto也是。但是您必须删除SetConjuntos中分配的(通过new)数据。请参阅@Barry 的评论。 -
顺便说一句,我尊重你使用
valgrind- 没有多少初学者使用它。甚至更多 - 很多专业人士不使用它.. -
如果
SetConjuntos的析构函数中的delete[]导致分段错误,则说明您在其他地方有问题 - 它应该在那里。不过,您应该在该类中有一个赋值运算符。 -
附带说明,您可能希望使用初始化列表而不是在构造函数的主体中初始化
datos类中的datos成员。就像现在一样,您的程序调用datos的默认构造函数,然后调用operator=运算符。最好只使用初始化列表中的复制构造函数进行初始化。一般来说,最好尽可能使用初始化列表。在您的情况下,您可以将它们用于所有构造函数中的所有数据成员。
标签: c++ class memory-leaks valgrind destructor