C++ 函数delete 问题;

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++ 函数delete 问题;相关的知识,希望对你有一定的参考价值。

#include <iostream>
using namespace std;
class cmessage

public:
cmessage(char* g)

int i=strlen(g)+1;
f=new char[i];
strcpy(f,g);



~cmessage()

cout<<"called the destructor"<<endl;
delete []f;

private:
char *f;
;
void messfun(cmessage f)

return;


int main()


cmessage g("lisng laiye");
messfun(g);
return 0;


添加了 delete [] f; 运行时就弹出终止的窗口 请问路高手这是咋回事捏

messfun是值传递的,g作为参数传递的时候是复制给messfun函数的 f 参数,所有成员(实际上也只有一个指针成员)复制给这个参数,当messfun函数返回的时候,f 的生命期结束,调用析构函数,执行delete []f;。然后main函数返回,g的生命期结束,这个时候delete []运算符作用在哪个变量上,这个变量指向哪里是很容易找到的……追问

我把delete [] f ; 去掉
然后在messfun(g);后面添加 g.show()以显示f指向的字符串 结果运行成功了 依你说析构函数不是已经将f调用delete[]删掉了吗

追答

好吧是我表述不清……

messfun函数返回时,调用析构函数,【析构函数】内部执行delete []f;释放参数 f 的成员变量 f 指向的内存空间,而这时候g指向的是同样的空间,因此main函数返回的时候调用析构函数销毁 g的时候delete []运算符释放的是已经释放过的的空间……

删掉析构函数中的delete [] f ; 则两次delete []都不存在,留下则两次都存在……

追问

刚才没看清楚 不过现在好像明白了
呢能告诉我 如果 "两次delete []都不存"
该怎样去掉动态分配的内存呢

追答

不使用默认的复制构造函数,而定义自己的复制构造函数,使复制构造之后 f 和 g 的成员指针指向不同的地址大概是最好的办法……
如果一定要让两个cmessage对象的成员指针指向相同的地方,也可以使用标准头文件中的智能指针shared_ptr来管理内存,虽然shared_ptr是新标准才有的东西,不过大多数较新的编译器应该都支持……

参考技术A 这类类都必须自己实现 cmessage(const cmessage&r) 构造函数
调用 messfun时 调用了默认的拷贝构造函数 ,该函数依次对所有成员进行一次拷贝操作,所以你的 f被释放了两次。
参考技术B

    delete[] 是delete一个数组,指针不需要加[]

    当把g传递给messfun时,实际执行的是 cmessage f = g; 只是简单的把g.f复制给f.f,但是却指向同一块内存,所以当函数结束时调用一次析构,释放堆内存,当main函数结束时又调用一次析构,又再次释放,此时发现要被释放的内存不存在了,所以报错,double free.重载operator=运算符即可.

参考技术C 上面回答的都很好了,对于类中存在指针成员变量的,使用上应该格外小心。默认的构造拷贝函数只是单纯的复制值,所以复制后的对象中指针f指向的是之前的对象中的f的内存,析构时会错误释放非自己new的内存。VS2010中居然代码没崩,感觉在VS中可能那个函数可能直接优化掉了。 参考技术D 浅拷贝 请看书......

C++中delete与 delete []区别

new调用构造函数,delete会调用对象的析构函数。

malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。
delete只会调用一次析构函数,而delete[]会调用每一个数组元素的析构函数。

在More Effective C++中有更为详细的解释:“当delete操作符用于数组时,它为每个数组元素调用析构函数,然后调用operator delete来释放内存。”

delete与new配套,delete []与new []配套。

VC6 新建一个单文档工程;

加入一个普通类;名字为T;

加入后如下;

 

在构造和析构函数各加入一句代码;

 

添加一个菜单;菜单处理函数如下;

void CDeltestView::OnMenuitem32771() 

	// TODO: Add your command handler code here
	const int NUM = 3;
	CString str1;
 
	T* p1 = new T[NUM];
	//cout << hex << p1 << endl;
	//  delete[] p1;
	str1.Format("p1: %x",p1);
	AfxMessageBox(str1);
	delete p1;
 
	T* p2 = new T[NUM];
	//cout << p2 << endl;
	str1.Format("p2: %x",p2);
	AfxMessageBox(str1);
	delete[] p2;

点击菜单;运行到第一段代码时;

弹出3次 构造; 

 

然后显示p1的值;

 

之后弹出一次 析构;

 

运行到第二段代码时;也是先弹出3次 构造;

然后弹出显示p2的值;

 

然后弹出了3次 析构;

 

 

以上是关于C++ 函数delete 问题;的主要内容,如果未能解决你的问题,请参考以下文章

C++ 【错误求帮改】构造函数、析构函数,delete等编程时的问题

c++中,析构函数和delete各有啥作用啊

C++构造函数的default和delete

C++中delete与 delete []区别

C++:= default & = delete

c++构造函数中使用new,析构函数用delete删除,出错