c++new不delete - CSDN
  • 描述 c++只,new了对象, 如果在后续进行 delete删除掉指向该对象的指针, 结果将是main函数执行结束后也执行析构函数, 对象并没有释放。 演示 建议 new ,delete一定要配合使用 ...

    描述

    c++只,new了对象,
    如果不在后续进行 delete删除掉指向该对象的指针,
    结果将是main函数执行结束后也不执行析构函数,
    对象并没有释放。

    演示在这里插入图片描述

    建议

    new ,delete一定要配合使用

    展开全文
  • C语言中我们在堆上开辟内存时,用到的是malloc和free,可是在C++中却引入了新的开辟内存和释放内存的方法,即newdelete。那么它们之间有什么一样,原理又是怎样的呢? 一、malloc/free和new/delete的区别? 1...

    C语言中我们在堆上开辟内存时,用到的是malloc和free,可是在C++中却引入了新的开辟内存和释放内存的方法,即new和delete。那么它们之间有什么不一样,原理又是怎样的呢?

    一、malloc/free和new/delete的区别?

    1、malloc和free是函数,new和delete却是C++的运算符

    2、malloc只能开辟空间,new既能开辟空间还可以初始化。new一次会调用一次构造函数,delete一次也会调用一次析构函数。

    3、malloc内存开辟失败时会返回NULL指针,但new开辟内存失败时不返回NULL指针,而是抛出bad_alloc类型的异常

    4、malloc在堆上申请的内存是void*类型,需要强转成自己需要的类型。new则在申请内存的时候就已经明确要申请的内存类型。

    二、C语言中已经有了malloc/free,C++中为什么还要有new/delete?

    1、首先malloc/free,new/delete都可以用于申请动态内存和释放内存。对于非内置数据类型的对象而言,malloc/free无法满足此种动态对象的要求。因为对象在创建的同时会自动调用构造函数,消亡之前会自动调用析构函数。因为malloc/free是库函数而不是运算符,不在编译器控制权限内,不能把构造函数和析构函数的任务强加于malloc/free。但是C++中new可以完成动态内存分配和初始化工作,delete能够完成清理与释放内存的工作。

    2、此时又有了一个新的问题,既然new/delete的功能可以覆盖掉malloc/free,为什么C++中不把malloc/free淘汰掉呢?

    因为C++程序经常要调用C函数,而C程序只能用malloc/free来管理动态内存。而且malloc/free,new/delete一定要配对起来使用。如果用free来释放new出来的内存,那么很有可能因为无法析构new创建的对象来导致程序出错。如果用delete来释放malloc申请的动态内存,虽然程序不会出错,但是会导致程序可读性变差。

    三、C++中 new/delete运算符重载

    #include<iostream>
    #include<list>
    #include<map>
    using namespace std;
    
    //只负责内存开辟
    void *operator new(size_t size)
    {
    	cout << "operator new" << endl;
    	void *p = nullptr;
    	p = malloc(size);
    	if(p == nullptr)
    		throw bad_alloc();
    	return p;
    }
    //只负责释放内存
    void operator delete(void *ptr)
    {
    	cout << "operator delete" << endl;
    	free(ptr);
    }
    
    //只负责内存开辟
    void *operator new[](size_t size)//size_t自己计算size大小
    {
    	cout << "operator new[]" << endl;
    	void *p = nullptr;
    	p = malloc(size);
    	if(p == nullptr)
    		throw bad_alloc();
    	return p;
    }
    //只负责释放内存
    void operator delete[](void *ptr)
    {
    	cout << "operator delete[]" << endl;
    	free(ptr);
    }
    int main()
    {
    	int *p1 = new int;
    	delete p1;
    
    	int *p2 = new int[10];
    	delete []p2;
    	return 0;
    }


     

    我们可以看到代码的运行结果中,每次会调用相应的重载函数。而new和delete的重载函数实现则是依赖malloc和free实现的。只是new和delete,不管是申请内存还是释放内存,会因为分配对象的内存是一个字节的指针还是一个数组(多个字节)来调用不同的函数。所以new和delete用于申请和释放一个字节的内存,而new []和delete []则用于申请和释放多个字节的内存。但是如果不匹配使用,会造成什么问题呢?

    int main()
    {
        int *p = new int[2];
       //delete []p;    ok
        delete p;
    }

    如果程序申请的是8个字节的内存,如果执行delete p,则会引起程序崩溃。

    原理如下:

    如果用new申请一段内存时,内存会自动在首部分配4个字节的空间,用来存储给多少对象分配了空间,也就是存储对象的个数。而真正申请到予以使用的内存空间则会在这四个字节之后。

    拿上面例子来说,p申请到的是以0x104为起始地址的8个字节的内存,但是会在其首部分配4个字节的空间用来存储对象的个数。如果释放内存的时候,执行 delete []p; 编译器在见到[]运算符的时候,会自动在p的真实地址0x104的基础上减4的到0x100,然后先释放p数组内每个元素的内存(0x104、0x108),然后释放数组的内存(0x100)。

    但是如果执行 delete p; 编译器认为p只是一个字节(0x104 - 0x108)的对象,在new的时候不会给它分配4个字节的内存用来存储对象的个数。所以它直接从0x104释放内存。但是p真实的内存空间有12个字节,所以引起程序崩溃。

     

     

    展开全文
  • C++ newdelete 的讲解

    2019-01-01 21:11:56
    对于new来说就有 new operator、operator new、placement newnew operator[]等。对于 delete 也有 delete operator、poerator deletedelete operator[] 等。下面就进行按个整理。 1、new operator 平...

    概述

    运算符 new 和 delete 看起来很简单,但是它们也有不少的知识点。对于new来说就有 new operator、operator new、placement new 和 new operator[]等。对于 delete 也有 delete operator、poerator delete、delete operator[] 等。下面就进行按个整理。

    1、new operator

    平时申请动态内存的 new 操作就是new operator。它其实由两个步骤完成:

    1、分配足够的内存,用来放置某类型对象
    2、调用构造函数,为刚才分配内存中的那个对象设定初值

    new operator 调用某个函数,执行内存分配的动作,这个函数就是 operator new。

    2、operatr new

    上面说了一个分配内存的函数叫 operator new ,可以用来改变内存分配行为。其函数声明通常为:

    void* operator new( size_t size);
    

    此函数返回一个指针,指向一块原始的、未设初始值的内存。size_t是分配内存的大小。

    你可以对 operator new 重载,加上额外的参数,但第一个参数类型必须总是 size_t。

    和malloc一样,operator new 唯一的任务就是分配内存。它不知道什么时候进行初始化操作。

    3、placement new

    在已分配好的内存上只调用对象的构造函数进行对象构建,需要使用placement new。例如:

    class Widget
    {
    public:
    	Widget( int widgetSize )
    	......
    }
    
    Widget* constructWidgetInBuffer( void* buffer, int widgetSize )
    {
    	return new ( buffer ) Widget ( widgetSize );
    }
    

    此函数返回一个指针,指向 Widget 对象,它被构造于传递给次函数的内存缓冲区上。

    其实placement new 是 operator new 的重载用法,其中指定一个额外自变量(buffer)作为 new operator “隐式调用operator new”时所用。类似于:

    void* operator new ( size_t, void* location )
    {
    	return location;
    }
    

    size_t是哑元参数,为了防止编译器报错。

    4、operator delete

    为了避免资源泄漏,每一个动态分配行为都必须匹配一个相应的释放动作

    operator delete 就是 operator new 对应的版本,通常声明如下:

    void operator delete ( void* memoryToBeDeallocated );
    

    和free()一样,此函数只会进行内存的释放,不会做其它动作。

    5、delete operator

    delete operator 是 new operator 的对应版本,它首先调用对象的析构函数,然后调用operator delete函数进行内存的释放。如果你这样写代码:

    Widget* ptr = new Widget(10);
    ......
    delete ptr;
    

    则编译器会给扩展成类似的代码:

    ptr->~Widget();
    operator delete(ptr);
    

    释放内存的函数要和申请内存的函数匹配使用

    6、数组的 new

    上面介绍的函数都只在一个对象上操作。对于数组而言,使用的仍然是new operator。例如:

     Widget* ptr = new Widget[ 10 ];
    

    虽然使用相同的 new operator , 但是行为与之前的产生单个对象的情况略微不同。主要有两点:

    1、一个名为operator new[] 的函数负责分配内存。也可以被重载。
    2、调用构造函数的次数不一样。数组版的 new operator 必须针对数组中的每个对象调用一个构造函数。

    它是如何记录元素的个数?在申请内存时,会额外配置一个内存放置元素的个数

    7、数组的 delete

    数组的delete要使用[ ],它会为每个数组中的元素调用析构函数。如:

     Widget* ptr = new Widget[ 10 ];
     ......         
     delete[] ptr;
    

    和new operator一样,也分为两个步骤:
    1、对数组中的每个元素调用析构函数。
    2、调用 operator delete[] 释放内存。

    只有的[] 出现时,编译器才寻找数组的维度,否则它便假设只有单独一个object要被删除。如:

    delete ptr;
    

    则只能调用数组第一个元素的析构函数,其它元素不会调用析构函数。然后调用 operator delete[] 释放内存。

    8、总结

    通过上面可以看出 new operator 就是先进行了 operator new ,然后在调用placement new。数组就相当于重复调用。

    new operator 和 delete operator 是语言内建的,就像sizeof一样,不能改变其意义。但是它们所调用的内存分配/释放函数则不然。想要定制new operator 和 delete operator 的行为,我后面会进行整理。

    感谢大家,我是假装很努力的YoungYangD(小羊)。

    参考资料:
    《More Effective C++》
    《深度探索 C++ 对象模型》

    展开全文
  • c++newdelete的用法总结与注意事项
    new运算符使用的一般格式为   new 类型 [初值]   用new分配数组空间时不能指定初值。如果由于内存不足等原因而无法正常分配空间,则new会返回一个空指针NULL,用户可以根据该指针的值判断分配空间是否成功。new int;//开辟一个存放整数的存储空间,返回一个指向该存储空间的地址(即指针)   
    new int(100);//开辟一个存放整数的空间,并指定该整数的初值为100,返回一个指向该存储空间的地址  
    new char[10];//开辟一个存放字符数组(包括10个元素)的空间,返回首元素的地址   

    new int[5][4];//开辟一个存放二维整型数组(大小为5*4)的空间,返回首元素的地址

    float *p=new float (3.14159);//开辟一个存放单精度数的空间,并指定该实数的初值为//3.14159,将返回的该空间的地址赋给指针变量p   

    delete运算符使用的一般格式为   delete [ ]指针变量   
    例如要撤销上面用new开辟的存放单精度数的空间(上面第5个例子),应该用   delete p;  
    前面用“new char[10];”开辟的字符数组空间,如果把new返回的指针赋给了指针变量pt,则应该用以下形式的delete运算符撤销该空间:   
      delete [] pt;//在指针变量前面加一对方括号,表示是对数组空间的操作   

    开辟空间以存放一个结构体变量例子。   

    [cpp] view plain copy
    
        #include <iostream>     
        #include <string>     
        using namespace std;  
           struct Student//声明结构体类型Student  
           {  
                        string name;     
                 int num;     
                 char sex;  
           };  
         int main( )     
        {  
                Student *p; //定义指向结构体类型Student的数据的指针变量  
           p=new Student;//用new运算符开辟一个存放Student型数据的空间  
           p->name=″WangFun″; //向结构体变量的成员赋值  
           p->num=10123;  
           p->sex='m';  
               cout<<p->name<<endl<<p->num<<endl<<p->sex<<endl;//输出各成员的值  
           delete p;//撤销该空间  
          return 0;     
        }     
        运行结果为   Wang Fun 10123 m  
        指针删除与堆空间释放。删除一个指针p(delete p;)实际意思是删除了<span style="color:#FF0000;">p所指的目标(变量或对象等),释放了它所占的堆空间,而不是删除p本身</span>(指针p本身并没有撤销,它自己仍然存在,该指针所占内存空间并未释放),释放堆空间后,p成了空指针。  
        #include<iostream>  
        using namespace std;  
        int main(){  
            int *a=new int(10);  
            cout<<*a;  
            delete a;  
            cout<<a;  
            return 0;  
        }   
        输出结果为 100xe42f00  
    使用注意事项

    1. new 和delete都是内建的操作符,语言本身所固定了,无法重新定制,想要定制new和delete的行为,徒劳无功的行为。

    2. 动态分配失败,则返回一个空指针(NULL),表示发生了异常,堆资源不足,分配失败。

    3. 指针删除与堆空间释放。删除一个指针p(delete p;)实际意思是删除了p所指的目标(变量或对象等),释放了它所占的堆空间,而不是删除p本身(指针p本身并没有撤销,它自己仍然存在,该指针所占内存空间并未释放),释放堆空间后,p成了空指针。

    4. 内存泄漏(memory leak)和重复释放。new与delete 是配对使用的, delete只能释放堆空间。如果new返回的指针值丢失,则所分配的堆空间无法回收,称内存泄漏,同一空间重复释放也是危险的,因为该空间可能已另分配,所以必须妥善保存new返回的指针,以保证不发生内存泄漏,也必须保证不会重复释放堆内存空间。

    5. 动态分配的变量或对象的生命期。我们也称堆空间为自由空间(free store),但必须记住释放该对象所占堆空间,并只能释放一次,在函数内建立,而在函数外释放,往往会出错。

    6. 要访问new所开辟的结构体空间,无法直接通过变量名进行,只能通过赋值的指针进行访问。

        用new和delete可以动态开辟和撤销地址空间。在编程序时,若用完一个变量(一般是暂时存储的数据),下次需要再用,但却又想省去重新初始化的功夫,可以在每次开始使用时开辟一个空间,在用完后撤销它。

    展开全文
  • 在之前的“C/C++内存管理方式”一文中,我们认识到了C++的内存管理是通过newdelete算符实现的。那么这篇文章会和大家共同探索一下newdelete的背后到底是什么样子的… newdelete的实现原理 1 内置类型 如果申请...
  • newdelete运算符用于动态分配和撤销内存的运算符 new用法:  1. 开辟单变量地址空间  1)new int; //开辟一个存放数组的存储空间,返回一个指向该存储空间的地址.int *a = new int 即为将一个int类型的地址...
  • c++newdelete的使用

    2018-05-08 07:00:10
    一、定义 首先先明确一点,new和delete是c++中用于申请和释放内存的,其次new和delete要成对使用 最后newdelete不能和malloc和free混用二、使用 先搞清楚使用newc++内部的机制 1、当初始化一个对象时 new--...
  • 前言Effective C++ rule 16规则,让我重新认识了deletenew在处理数组时候的方式。new 有两种形式的new,一种是生成一个对象的operator New,另一个是用于数组的operator new []。同时 operator delete也分普通版本的...
  • 浅谈 C++ 中的 new/deletenew[]/delete[] operator new 和 operator delete 这两个其实是 C++ 语言标准库的库函数,原型分别如下: void *operator new(size_t); //allocate an object void *operator delete...
  • C++newdelete详解

    2019-06-21 15:03:54
    C++中如果要在堆内存中创建和销毁对象需要借助关键字newdelete来完成。比如下面的代码 class CA { public: CA():m_a(0){} CA(int a):m_a(a){} virtual void foo(){ cout<<m_a<<endl;} ...
  • newdeleteC++预定的操作符,它们一般需要配套使用。new用于从堆内存申请一块空间,一般动态用于动态申请内存空间,即根据程序需要,申请一定长度的空间,而delete则是将new申请的空间释放。 new 有以下的三种...
  • c++中的newdelete

    2018-07-05 00:03:22
    2.虽然c++中也有malloc和free,区别在于,newdelete在对类操作执行时会分别调用类的构造和析构函数;下面举个例子说说用法吧:new int; //开辟一个存放整数的存储空间,返回一个指向该存储空间的地址(即指针)new ...
  • C++newdelete实现原理

    2014-09-01 02:14:10
    new操作 delete操作 new[]操作 delete[]操作
  • new/deleteC++的运算符;类似于malloc/free,程序运行(动态)得开辟内存空间(堆); b. new 可以为内置类型的变量开辟空间,数组变量,类的对象开辟空间。这是在堆上开辟内存,返回一个指向该内存空间的地址。 内置...
  • 篇博文主要是分析了C++ new()和构造函数的执行,delete()与析构函数的调用方式,通过全局重载和局部重载看清楚调用的关系[cpp] view plain copyusing namespace std; #include &lt;iostream&gt; #...
  • c++详解【newdelete

    2016-11-21 09:22:46
    说起newdelete,了解过c++的人应该都知道吧,它是用来分配内存和释放内存的两个操作符。与c语言中的malloc和free类似。 c语言中使用malloc/calloc/realloc/free进行动态内存分配,malloc/calloc/realloc用来在堆...
  • newdelete运算符用于动态分配和撤销内存的运算符new用法: 1. 开辟单变量地址空间 1)new int; //开辟一个存放数组的存储空间,返回一个指向该存储空间的地址.int *a = new int 即为将一个int类型的地址赋值给...
  • C++中重载newdelete的使用
  • C++ newdelete对象

    2019-10-09 11:55:56
    static void *operator new(size_t size); static void operator delete(void *phead); //static void *operator new[](size_t size); //static void operator delete[](void *phead);...
  • 最近一直在啃 C++ Primer 中文版第4版,发现 C++newdelete应用遍布全书,现对其使用作简单总结。在C++中,可以使用newdelete动态创建和释放数组或者单个对象,现在对它们的使用一一道来。 1.创建动态...
1 2 3 4 5 ... 20
收藏数 205,707
精华内容 82,282
热门标签
关键字:

c++new不delete