1. 我在写一个程序使用内存分配(自己写的类是在类构造时分配空间),分配时没错,可是释放(是在类析构时)就出错。我把析构时的代码去掉就没事了,是怎么回事那?难道分配的内存不用释放?
我用的是win2000,编译环境是VC6.0。
局部代码如下:
template <class Type>
CSqList<Type>::CSqList(void)
{
//elem是一个Type类型的指针,是个私有变量
elem=(Type *)malloc(LIST_INIT_SIZE*sizeof(Type));
if(!elem)
{
MessageBox(NULL,"内存不足!!!","程序错误",MB_OK);
}
ListSize=LIST_INIT_SIZE;
Length=0;
IsSort=0;
}template <class Type>
CSqList<Type>::~CSqList()
{
//free(elem);
}+重载如下:
template <class Type>
CSqList<Type> CSqList<Type>::operator+(CSqList &B) //+运算符操作
{
int Len;
Len=Length+B.Length;
CSqList temp(Len);
memcpy(temp.elem,elem,Length*sizeof(Type));
memcpy(&(temp.elem[Length]),B.elem,B.Length*sizeof(Type));
temp.Length=Len; return temp;
}比如运行a=a+b时,它调用了析构函数,然后就出错了!怎么回事?2. new和malloc有什么区别,他们具体是怎么实现的?
3. 内存的分配是不是和所用的操作系统有关,希望详解。
我用的是win2000,编译环境是VC6.0。
局部代码如下:
template <class Type>
CSqList<Type>::CSqList(void)
{
//elem是一个Type类型的指针,是个私有变量
elem=(Type *)malloc(LIST_INIT_SIZE*sizeof(Type));
if(!elem)
{
MessageBox(NULL,"内存不足!!!","程序错误",MB_OK);
}
ListSize=LIST_INIT_SIZE;
Length=0;
IsSort=0;
}template <class Type>
CSqList<Type>::~CSqList()
{
//free(elem);
}+重载如下:
template <class Type>
CSqList<Type> CSqList<Type>::operator+(CSqList &B) //+运算符操作
{
int Len;
Len=Length+B.Length;
CSqList temp(Len);
memcpy(temp.elem,elem,Length*sizeof(Type));
memcpy(&(temp.elem[Length]),B.elem,B.Length*sizeof(Type));
temp.Length=Len; return temp;
}比如运行a=a+b时,它调用了析构函数,然后就出错了!怎么回事?2. new和malloc有什么区别,他们具体是怎么实现的?
3. 内存的分配是不是和所用的操作系统有关,希望详解。
解决方案 »
- 求助,关于VC中MessageBox的问题~~
- 如何使CPropertySheet、CPropertyPage做的向导下一步按钮置灰?
- mfc对话框工程在AfxWinMain崩溃
- 打开防火墙,程序就死机???
- 请教 DLL 和 主线程间的执行顺序~
- 熟悉potmessage、getmessage的精英请进
- 請問一個矩陣翻轉的算法問題!
- SOS!!! 在线等待!!! HELP ME!!!
- 请问:哪儿有《21天学会Visual C++数据库编程》的附带光盘源代码下载?谢谢!
- 急:问一个语法问题:missing ';' before '*'
- 关于串口编程VARIANT 赋值给COleSafeArray的问题(分不够再加)
- 如何获得优盘的盘符!?各位老大,帮忙!!
他们最大的不同大概就是在于new能完成动态内存分配和初始化工作
delete 能完成清理与释放内存工作
malloc/free是库函数而不是运算符,不在编译器控制权限之内
不能执行构造函数与析构函数
创建动态对象时区别比较明显
内存的分配当然和所用的操作系统有关,在win2000下一般不会出现
因为系统内存分配而导致的错误
至于你的问题,把free()移到构造函数中试试吧
template <class Type>
CSqList<Type> CSqList<Type>::operator+(CSqList &B) //+运算符操作
{
int Len;
Len=Length+B.Length;
CSqList temp(Len);
memcpy(temp.elem,elem,Length*sizeof(Type));
memcpy(&(temp.elem[Length]),B.elem,B.Length*sizeof(Type));
temp.Length=Len; return temp;
}——你的代码有问题:
你在函数中定义了一个临时对象:
CSqList temp(Len);
并返回它的值:
return temp;函数采取的值返回:
CSqList<Type>.....这样,在返回时,编译器会生成一个临时对象,并用你的临时对象来初始化它:
CSqList functemp = temp;
....由于你没有定义"="操作符,因此编译器会对成员变量进行值拷贝,编译器生成的临时对象的elem成员就直接复制过去了。实验室要关门了,就写这么多了
反正,你还要重载"="操作符!在其中对elem进行必要操作。
好运....^_^
学习学习ing
这段程序还有一个缺陷,对于模版类,用malloc是不会调用其构造函数的,所以应该用new和delete。
你一开始在析构函数中释放了内存:
template <class Type>
CSqList<Type>::~CSqList()
{
free(elem);
}
那么你的重载函数:
template <class Type>
CSqList<Type> CSqList<Type>::operator+(CSqList &B) //+运算符操作
{
int Len;
Len=Length+B.Length;
CSqList temp(Len);
memcpy(temp.elem,elem,Length*sizeof(Type));
memcpy(&(temp.elem[Length]),B.elem,B.Length*sizeof(Type));
temp.Length=Len; return temp;
}中的局部变量在出函数体时,其所分配的内存也释放掉了,正如上面所说,由于你没有定义"="操作符,因此编译器会对成员变量进行值拷贝,编译器生成的临时对象的elem成员就直接拷贝你的局部变量的elem成员,导致临时对象的elem成员指向一块已释放的内存,导致错误。
后来, 你在析构函数中把释放内存的语句注释掉了,因此,编译器生成的临时对象的elem成员直接拷贝你的局部变量的elem成员后,指向的是一块有效内存,因此不会出错,不过,这块内存永远不能回收了。。
有两个解决办法:
1。重载"="操作符
template <class Type>
CSqList<Type>& CSqList<Type>::operator=(const CSqList &B)
{
Length=B.Length;
elem=(Type *)malloc(Length*sizeof(Type));
memcpy(elem,B.elem,Length*sizeof(Type)); return *this;
}
2.改写+重载,改为引用返回:
template <class Type>&
CSqList<Type> CSqList<Type>::operator+(CSqList &B) //+运算符操作
{
int Len;
Len=Length+B.Length;
CSqList *ptemp = new CSqList(Len);
memcpy(ptemp->elem,elem,Length*sizeof(Type));
memcpy(ptemp->elem+Length,B.elem,B.Length*sizeof(Type));
ptemp->Length=Len; return *ptemp;
}
,free也不会调用该类的析构函数,因此,还是建议用new和delete:
elem=(Type *)malloc(LIST_INIT_SIZE*sizeof(Type));
改为:
elem = new Type[LIST_INIT_SIZE]free改为:
delete[] elem
1。重载"="操作符
template <class Type>
CSqList<Type>& CSqList<Type>::operator=(const CSqList &B)
{
free(elem); //释放掉原来分配的内存
Length=B.Length;
elem=(Type *)malloc(Length*sizeof(Type));
memcpy(elem,B.elem,Length*sizeof(Type)); return *this;
}
great responsibility,cheers!
我想问一下,那有关于算符重载的文章,我想看看。
还有
template <class Type>&
CSqList<Type> CSqList<Type>::operator+(CSqList &B)
这样写具体实现代码编译不过去,还有函数声明应该怎么写呢?
template <class Type>
CSqList<Type>& CSqList<Type>::operator+(CSqList &B) //+运算符操作
{
int Len;
Len=Length+B.Length;
CSqList *ptemp = new CSqList(Len);
memcpy(ptemp->elem,elem,Length*sizeof(Type));
memcpy(ptemp->elem+Length,B.elem,B.Length*sizeof(Type));
ptemp->Length=Len; return *ptemp;
}
template <class Type>
class CSqList
{
...
CSqList& operator+(const CSqList &B);
...
}template <class Type>
CSqList<Type>& CSqList<Type>::operator+(const CSqList<Type> &B) //+运算符操作
{
int Len;
Len=Length+B.Length;
CSqList *ptemp = new CSqList(Len);
memcpy(ptemp->elem,elem,Length*sizeof(Type));
memcpy(ptemp->elem+Length,B.elem,B.Length*sizeof(Type));
ptemp->Length=Len; return *ptemp;
}
我想问一下,CSqList *ptemp = new CSqList(Len)以后,分配的空间释放了吗?
void fun(...)
{
...
c = a + b;//a,b,c都是你的类实例
...
}其中的c就是+重载中的下句生成的:
CSqList *ptemp = new CSqList(Len);
在函数执行完了后,c被析构,也就是会调用c的析构函数,其所申请的内存自然被释放了(当然了,你的析构函数要负责释放内存)CSqList& operator+(const CSqList &B)
——const修饰是为了避免在函数体中修改了参数的值。在+重载中,参数b的值是不应该变的,因此我给他加了一个const修饰,这是一种比较好的预警机制
在函数完成时 return *ptemp;
这样的话应该ptemp这个指针释放了,还是它所指的空间释放了呢?
像我一开始写的+运算符,在函数结束时局部变量已被释放了,我以为它已经被压入栈中,可是空间已被释放,所以出错,那你这个是怎么回事呢?
谢谢大侠指点!!! ^_^
在函数完成时 return *ptemp;
这样的话应该ptemp这个指针释放了,还是它所指的空间释放了呢?
——这样写,就是ptemp这个指针被释放了,而他所指的空间并没有被释放你一开始的代码中是这样写的:
...
CSqList temp(Len);
...这是在函数的栈空间定义的局部变量,这样,在函数数结束时就会调用局部变量temp的析构函数,你又在析构函数中调用了free,因此,空间就释放掉了而这样写:
CSqList *ptemp = new CSqList(Len);
是在堆上申请的内存,因此在函数结束后不会调用对象的析构函数的
会释放的,比如你有一个函数:
void fun(...)
{
...
c = a + b;//a,b,c都是你的类实例
...
}其中的c就是+重载中的下句生成的:
CSqList *ptemp = new CSqList(Len);在fun函数执行完了后,c被析构,也就是会调用c的析构函数,其所申请的内存自然被释放了(当然了,你的析构函数要负责释放内存)
template <class Type>
CSqList<Type>::~CSqList()
{
free(elem);
}
因为此时elem成员指向的内存就是需要释放的内存
我指得是CSqList *ptemp = new CSqList(Len),这个对象分配的空间的释放,就是new分配的空间的释放。我应在什么地方释放呢?万分感谢common_man同志的指导!!!