C++深入讲解new与deleted关键字的使用

目录
  • 可执行程序的虚拟地址空间
  • 1.new的运算符用法(关键字)
  • 2.new的函数用法
  • 3.定位new
  • 4.new创建对象
  • 5.delete
  • 6.对于内置类型new/delete/malloc/free可以混用
  • 7.使用注意事项

可执行程序的虚拟地址空间

  1. 内核:存放操作系统
  2. 栈区:函数的形参,非静态的局部变量,函数现场 保护数据等等,栈是向下增长的。
  3. 共享库的内存映射区域:用于装载一个共享的动态内存库。用户可使用系统接口创建共享内存,做进程间通信。
  4. 堆区:用于程序运行时动态内存分配,堆是可以上增长的。
  5. 数据:存储全局数据和静态数据,分为.bss和.data 。
  6. 代码:可执行的程序(机器指令)和常量数据。

1.new的运算符用法(关键字)

int* p= new int(10);

这里的new的用法是当作运算符的用法,该用法一共有四个步骤:

  1. 计算类型
  2. 申请一个空间(因为new的底层是malloc)
  3. 将所取得的空间初始化
  4. 将申请到的地址返回

2.new的函数用法

new当作函数用法使用的是时候,类似malloc,都是申请一个空间,区别在于,返回值不同;当空间不足时malloc会返回一个“nullptr”,operator new会返回一个throw_bad的异常。

当我们加入一个nothrow后:

这样申请错误后,我们返回的是空指针。

对于malloc我们不可以进行初始化,new也不可以初始化。

所以当new作为函数时就相当于malloc。

3.定位new

定位new用法与构造new十分相似,是在已经确定的空间当中,构造一个对象,并将该对象放置到声明的空间当中。

int main()
{
	int n = 10;
	int* ipa = (int*)ma11oc(sizeof(int));
	int* ipb = (int*) : :operator new(sizeof(int) * n);
	new(ipa) int(20);
	new(ipb) int[]{ 1,2,3,4,5,6,7,8,9 };
	free(ipa);
	: :operator delete(ipb);
	return 0;
}

不需要开辟相应的空间 合法空间即可 给出某个地址 即可根据要求进行相应操作。

4.new创建对象

new创建对象特点:

  1. new创建对象需要指针接收,一处初始化,多处使用。
  2. new创建对象使用完需delete销毁。
  3. new创建对象直接使用堆空间,而局部不用new定义对象则使用栈空间。
  4. new对象指针用途广泛,比如作为函数返回值、函数参数等。
  5. 频繁调用场合并不适合new,就像new申请和释放内存一样。

new创建对象例子:

CTest*  pTest = new  CTest();
delete pTest;

pTest用来接收对象指针。

不用new,直接使用类定义申明:

CTest  mTest;

此种创建方式,使用完后不需要手动释放,该类析构函数会自动执行。

而new申请的对象,则只有调用到delete时再会执行析构函数,如果程序退出而没有执行delete则会造成内存泄漏。

C Test*  pTest = NULL;

但使用普通方式创建的类对象,在创建之初就已经分配了内存空间。

这类指针,如果未经过对象初始化,则不需要delete释放。

5.delete

delete运算符使用的一般格式为

 delete [ ]指针变量

例如要撤销上面用new开辟的空间用:

delete p; 

如果我们用“new char[10];”开辟的字符数组空间,把new返回的指针赋给了指针变量pt,则应该用以下形式的delete运算符撤销该空间:

  delete [] pt;

一般来说delete与new需要配对使用。

6.对于内置类型new/delete/malloc/free可以混用

  1. new/delete是C++中的运算符。malloc / free是函数。
  2. malloc申请内存空间时,手动计算所需大小,new只需类型名,自动计算大小;
  3. malloc申请的内存空间不会初始化,new可以初始化;
  4. malloc的返回值为void*,接收时必须强转,new不需要;
  5. malloc申请内存空间失败时,返回的是NULL,使用时必须判空;new申请内存空间失败时返回异常

7.使用注意事项

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

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

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

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

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

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

到此这篇关于C++深入讲解new与deleted关键字的使用的文章就介绍到这了,更多相关C++ new与deleted内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • c++动态内存管理详解(new/delete)

    目录 前言 用法上 对内置类型 对自定义类型 new/delete底层原理 重载类的专属operatornew和operatordelete 定位new new/delete与malloc/free区别总结 内存泄漏 总结 前言 想必大家对c语言的动态内存分配并不陌生,忘了的小伙伴也可以看看我的这篇文章C语言动态内存分配 c语言的动态内存分配由于有些地方用起来比较麻烦同时检查错误的机制不适合c++,因此c++引入new/delete操作符进行内存管理,下面我们来深入探讨c++为什么要引入new/

  • 一篇文章了解c++中的new和delete

    目录 new expression delete expression new[]和new() new[]和delete[] new的内存分布 placement new new失败处理 捕捉异常 禁用new的异常 new-handler 重载 重载全局的::operator new 重载局部的Foo::operator new 重载placement new 总结 new expression new一个类型,会创建一个该类型的内存,然后调用构造函数,最后返回该内存的指针 注意:该操作是原子性

  • 深入浅析C++的new和delete

    new和delete的内部实现 C++中如果要在堆内存中创建和销毁对象需要借助关键字new和delete来完成.比如下面的代码 class CA { public: CA()m_a(0){} CA(int a):m_a(a){} virtual void foo(){ cout<<m_a<<endl;} int m_a; }; void main() { CA *p1 = new CA; CA *p2 = new CA(10); CA *p3 = new CA[20]; delet

  • C++中new和delete的介绍

    介绍 1.malloc,free和new,delete区别. a.malloc,free是C/C++的标准库函数.new,delete是c++的操作符. b.malloc申请的是内存,严格意义不是"对象",new申请的可以理解为"对象",new 时会调用构造函数,返回指向该对象的指针. c.对于class类型,必须用new/delete来创建和销毁,自动调用构造和析构函数,malloc/free无法胜任. 2.使用new遵循原则: a.用new申请的内存,必须用de

  • C++的new和delete详解

    目录 1.new和delete的内部实现 2.placement技术 3.new和delete运算符重载 4.对象的自动删除技术 1.new和delete的内部实现 C++中如果要在堆内存中创建和销毁对象需要借助关键字new和delete来完成.比如下面的代码 class CA { public: CA()m_a(0){} CA(int a):m_a(a){} virtual void foo(){ cout<<m_a<<endl;} int m_a; }; void main()

  • 浅析C++ new的三种面貌

    1.new的三种面貌 C++中使用new运算符产生一个存在于Heap(堆)上对象时,实际上调用了operator new()函数和placement new()函数.在使用new创建堆对象时,我们要清楚认清楚new的三种面貌,分别是:new operator.operator new()和placement new(). 1.1new operator new operator是C++保留的关键字,我们无法改变其含义,但我们可以改变new完成它功能时调用的两个函数,operator new()和

  • 分享C++三种类型new类型的运算符使用详情

    目录 1.new操作符 2.::operator new 2.1原始调用 2.2重载1 2.3重载2 3.place new 1.new操作符 new operator,平时用的最多的new操作符,其对应delete operator,不能被重载,其包含两个操作(既申请空间,又调用构造函数) (1)使用::operator new申请内存 (2)调用类的构造函数 class CTestUse { public:     CTestUse() { cout << __FUNCTION__ <

  • C++ 使用new与delete需注意的原则

    C++的动态内存管理是通过new和delete两个操作来完成的,即用new来申请空间,用delete来释放空间.在使用new和delete时,注意以下原则. 1.new与delete需一一对应 用new操作申请空间,如果申请成功,必须在以后的某个时刻用delete释放该空间,既不能忘记释放,也不能多次释放.前者会引起内存泄露,后者会引起运行时错误.如下面的程序. #include <iostream> using namespace std; int main() { int *p; p=ne

  • C++使用new和delete进行动态内存分配与数组封装

    目录 1.使用new申请内存 2.使用delete释放内存 3.使用new申请内存时的初始值 4.使用new和delete申请和释放数组空间 5.用类封装new申请和释放的数组空间 6.使用new申请多维数组 1.使用new申请内存 在某些情况下,程序只有在运行期间才能确定所需内存大小,此时应该使用new申请内存.申请成功的情况下会返回首地址,通过指向首地址的指针可以访问申请的内存,使用new申请内存的的语法如下: new 数据类型(初始化参数列表); 下面的例子定义了Duck类型的指针,并通过

  • C++深入讲解new与deleted关键字的使用

    目录 可执行程序的虚拟地址空间 1.new的运算符用法(关键字) 2.new的函数用法 3.定位new 4.new创建对象 5.delete 6.对于内置类型new/delete/malloc/free可以混用 7.使用注意事项 可执行程序的虚拟地址空间 内核:存放操作系统 栈区:函数的形参,非静态的局部变量,函数现场 保护数据等等,栈是向下增长的. 共享库的内存映射区域:用于装载一个共享的动态内存库.用户可使用系统接口创建共享内存,做进程间通信. 堆区:用于程序运行时动态内存分配,堆是可以上增

  • C++深入讲解namespace与string关键字的使用

    目录 namespace 1.为什么使用namespace 2.namespace的定义 3.namespace的使用 4.使用using指示符 string 1.string的定义及初始化 2.访问string的内容 3.常用函数 namespace 首先声明:在C++中支持三种域局部域,名字空间,类域. 1.为什么使用namespace 在C++中可能会出现这样的情况:我们正在编写一个名为myj()函数的代码,但是另一个可用的库,它也具有相同的myj()函数.现在编译器无法知道代码中使用的m

  • C++示例讲解friend static const关键字的用法

    目录 一.友元函数 1.1重载operator<< 1.2友元函数 1.3友元类 二.关键字const 2.1const修饰类的成员函数 三.关键字static 3.1static类成员 3.2面试题 总结 一.友元函数 1.1重载operator<< 问题:现在我们尝试去重载operator<<,然后发现我们没办法将operator<<重载成成员函数.因为cout的输出流对象和隐含的this指针在抢占第一个参数的位置.this指针默认是第一个参数也就是左操

  • 举例讲解Java中final关键字的用法

    1. final variable final variable 就是一个常量,一旦被初始化就不可以被改变. class Test1 { final double PI = 3.14; //常量的名称最好大写 public Test1(){ PI = 3.14; } void test(){ System.out.println("PI is: " + PI); } public static void main(String[] args){ Test1 t = new Test1(

  • 举例讲解Java中synchronized关键字的用法

    synchronized关键字顾名思义,是用于同步互斥的作用的. 这里精简的记一下它的使用方法以及意义: 1. 当synchronized修饰 this或者非静态方法或者是一个实例的时候,所同步的锁是加在this或者实例对象引用上面的.比如a,b同为Main类的实例化对象,a调用被同步的方法,和b调用被同步的方法,没有形成互斥.但是不同线程的a对象调用被同步的方法就被互斥了. public synchronized void method(){ //-. } public void method

  • 精通JavaScript的this关键字

    JS中的this关键字让很多新老JS开发人员都感到困惑.这篇文章将对this关键字进行完整地阐述.读完本文以后,您的困惑将全部消除.您将学会如何在各种不同的情形正确运用this. 我们和在英语.法语这样的自然语言中使用名词一样地使用this.比如,"John飞快地跑着,因为他想追上火车".请注意这句话中的代指John的代名词"他".我们原本也可以这样表达,"John飞快地跑着,因为John想追上火车".按照正常的语言习惯,我们并不按第二种方式表达

  • C++中关键字Struct和Class的区别

    Struct和Class的区别 今天这篇博文主要讲解在C++中关键字struct和class的区别.这篇博文,将会系统的将这两个关键字的不同面进行详细的讲解. 从语法上来讲,class和struct做类型定义时只有两点区别: 1.默认继承权限,如果不指定,来自class的继承按照private继承处理,来自struct的继承按照public继承处理: 2.成员的默认访问权限.class的成员默认是private权限,struct默认是public权限.以上两点也是struct和class最基本的

  • asp.net中ADO SQL数据库 笔记汇总 持续更新中

    ADO连接数据库 1)获取连接字符串 方式一: 记住连接字符串 connectionString=" Integrated Security=True; server=. ; database=DBName" 方式二:在visual studio中,点击"视图"à服务资源管理器à右击左侧的"数据连接",选择"添加连接"à服务名: 为一个点.选择数据库名,然后点击"高级",然后复制底部的连接字符串 2)在we

  • Java语法之 Java 的多态、抽象类和接口

    目录 一.多态 1. 向上转型 2. 动态绑定 3. 方法重写 4. 向下转型 5. 关键字 super 6. 在构造方法中调用重写方法(坑) 7. 理解多态 8. 小结 二.抽象类 1. 概念 2. 注意事项 3. 抽象类的意义 3. 抽象类的作用 三.接口 1. 语法规则 2. 实现多个接口 3. 接口的继承 4. Comparable 接口 4. Comparator 接口 5. Cloneable 接口和深拷贝 上一篇文章:Java 基础语法之解析 Java 的包和继承 今天这章主要介绍

  • C语言指针和数组深入探究使用方法

    目录 1.数组参数和指针参数 1.1 一维数组传参 1.2 一级指针传参 1.3 二维数组参数和二级指针参数 1.4 野指针的问题 2.函数指针 3.函数指针数组 4.指向函数数组的指针 5.回调函数 6.一道笔试题 1.数组参数和指针参数 1.1 一维数组传参 这里在前几期我们已经初略的见识过了,但是这里我们要提一个概念,数组给函数传参是会发生降维的,降维成什么呢?我们看代码: 这里通过打印形参的大小,发现是 4,其实也不奇怪,目前我们是 32 位操作环境,所以一个指针也就是 4 个字节,所以

随机推荐