zoukankan      html  css  js  c++  java
  • 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对象结尾的几个字节!程序会错误地把这末尾的几个字节的内容当做虚表的地址,所以会引发内存访问错误。

    作者:starays
    链接:https://www.jianshu.com/p/fbf6cad613e9
    来源:简书
    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
  • 相关阅读:
    ES6中的reduce
    go.js 基本配置
    ES6(十二)类与对象
    ES6(十一)Proxy和Reflect
    ES6(十)map、set与数组和对象的比较
    ES6(九)set、map数据结构
    ES6(八)Symbol
    ES6(七)对象扩展
    hbase常识及habse适合什么场景
    Hbase与传统数据库的区别
  • 原文地址:https://www.cnblogs.com/l2017/p/6915315.html
Copyright © 2011-2022 走看看