c++ 用new后delete,而继续输出指针后果 new/new[]/delete/delete[]区别
1 #include<iostream> 2 #include<cstring> 3 #include <string.h> 4 5 int main(){ 6 7 int *a =new int[100]; 8 for(int i=0;i<100;i++){a[i]=i;} 9 char *b; 10 delete []a; 11 for(int i=0;i<1000000;i++){ 12 b=new char [100]; 13 b="dfdf";} 14 15 for(int i=0;i<100;i++){cout<<a[i]<<endl;} 16 cout<<endl<<a; 17 18 }
所以不要这样
1 #include<iostream> 2 #include<cstring> 3 #include <string.h> 4 using namespace std; 5 class Cbox{ 6 char * aa; 7 public: 8 int g ; 9 Cbox(const char *a){int length =(strlen(a)+1); 10 aa= new char[length +1]; 11 strcpy(aa,a); 12 cout<<"gouzao"<<endl;} 13 Cbox()=default; 14 ~Cbox(){delete aa;cout<<"xigou"<<endl;} 15 void show(){cout<<aa<<endl;} 16 }; 17 18 void display (Cbox a){ 19 a.show();} 20 21 22 23 24 int main(){ 25 char as[100]="""asd1200"; 26 Cbox a(as) ; 27 28 display(a); 29 a.show(); 30 } 31
因为这里实参是通过传值方式传递的,会用默认构造函数创建实参的副本,副本的指针跟实参的指针指向空闲存储器中同一个字符串。 超出函数作用域后,副本会析构,使副本里 的指针 指向的内存被释放。 但实参还是指着那个位置,所以可能出错。
malloc/new/new[] 申请了一块内存的时候,编译器实际上会在这块内存的头部保存一个 size_t 信息,记录了这块内存的大小。这个size信息是需要占用额外的空间的
在对 p指针进行free/delete/delete []操作的时候,实际上会先通过 *(p-sizeof(size_t))
来获得这块内存的大小,然后将内存归还给系统。
如果是内置类型 int char 用delete 和delete[]没区别
如果是类类型 有析构函数那些就有区别了。 delete只会对第一个对象调用析构函数,然后释放掉这一整块内存的空间(包括那些没执行析构函数的对象。(第二个第三个。。。。))
delete[]则会对每个对象都执行析构函数,然后释放掉这一整块内存的空间。
对于下面的两行代码:
Base * p = new Derived();
delete p;
如果derived有虚析构函数,那么deletep会调用虚析构函数
Base * p = new Derived[10];
delete [] p;
但当用数组时这里就有问题了,会出现内存访问错误。原因在于在执行 delete [] p的时候,实际上是这么执行的:
for (int i = 0; i < memory_size; i = i + sizeof(Base)) {
(Base *)((void * ) p + i)->~();
}
free(p);
在对数组中第一个对象执行析构函数的时候,结果是正常的;但是在对第二个对象执行析构函数的时候,由于Base对象和Derived对象的大小并不相同,(Base *)((void * ) p + i)
并不能找到虚表的地址——这个指针实际指向的并不是第二个Derived对象的开头,而是第一个Derived对象结尾的几个字节!程序会错误地把这末尾的几个字节的内容当做虚表的地址,所以会引发内存访问错误。
链接:https://www.jianshu.com/p/fbf6cad613e9
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。