C++ new、delete

C++中向系统申请堆内存的方法为使用new、new[]操作符,new申请单个对象的内存,new[]申请对象数组的内存。对应的delete、delete[]操作符将new、new[]操作符申请到的内存还给系统。使用new运算符的表达式被称为new表达式,相应的,使用delete运算符的表达式被称为delete表达式。

C++默认的new表达式有3种形式。

(1).最基本也是最常见的

new type

new type(initilalizers)

new type[size]

new type[size]{braced initializer list}

(2).指定不抛异常的

new(nothrow) type

new(nothrow) type(initializers)

new(nothrow) type[size]

new(nothrow) type[size]{braced initializer list}

(3).只创建对象不分配内存的

new(place_address) type

new(place_address) type(initializers)

new(place_address) type[size]

new(place_address) type[size]{braced initializer list}

而C++默认的delete表达式只有一种形式

delete   ptr

delete[] ptr

以单对象内存的分配为例:

new表达式1的工作原理如下:1.调用 void * operator new(size_t)函数分配内存 2.在第1步返回的内存上调用对象的构造函数 3.返回内存指针。

new表达式1在第1步和第2步都是可能抛出异常的。在第1步,如果系统没有足够内存可分配,void * operator new(size_t)函数会抛出 bad_alloc异常。在第2步,如果对象的构造函数抛出了异常,为了防止内存泄露,编译器会将异常捕获,然后调用 void operator delete(void *)函数回收内存,最后将异常再次抛出。

new表达式2的工作原理如下:1.调用 void *operator new(size_t ,const std::nothrow_t &)函数分配内存 2.在第1步返回的内存上调用对象的构造函数 3.返回内存指针。

new表达式2的第1步在分配不到内存的情况下不会抛出异常,而是返回空指针。在第2步,如果对象的构造函数抛出了异常,为了防止内存泄露,编译器也会将异常捕获,然后回收内存,但调用的函数是 void operator delete(void *,const std::nothrow_t &)。

new表达式3的工作原理如下:1.调用 void *operator new(size_t,void *)返回内存 2.在第1步返回的内存上调用对象的构造函数 3.返回内存指针。

new表达式3的第1步调用的 void *operator new(size_t,void *)不向系统申请内存,只是把第二个参数返回。这样,第2步对象的构造就是在用户指定的内存上进行的。第2步跟上面两个一样,也是对对象进行构造,但在构造函数抛出异常的情况下,回收内存时调用的函数为 void operator delete(void *,void *),这个函数啥都不干。

new表达式2、3又被称为定位new表达式。

delete 表达式的工作原理如下:1.调用对象的析构函数 2.调用 void operator delete(void *)回收内存。

如果是数组版本的new表达式、delete表达式,以上函数的对应版本为

void * operator new(size_t) 对应 void * operator new[](size_t)

void * operator new(size_t,const std::nothrow_t &) 对应 void * operator new[](size_t,const std::nothrow_t &)

void * operator new(size_t,void *) 对应 void * operator new[](size_t,void *)

void operator delete(void *) 对应 void operator delete[](void *)

void operator delete(void *,const std::nothrow_t &)对应 void operator delete[](void *,const std::nothrow_t &)

void operator delete(void *,void *) 对应 void operator delete[](void *,void *)

这以上12个函数都位于 标准库<new>中,除了 void *operator new(size_t,void *)这一类的四个函数外,其它8个函数都可以被用户自定义。

自定义途径有两种,第一种是在全局作用域中重新定义,第二种是在类作用域中重新定义。在namespace中定义这8个函数是错误的。如果是一般函数,第一种途径是会引发重定义错误的,但C++标准为new、delete开了后门。new、delete表达式在寻找实际应该使用哪个函数的顺序是这样的。如果是对象是类类型,则先在该类以及该类的基类的成员函数中寻找相应的函数,如果没有,则到全局作用域中去寻找。如果全局作用域中有用户自定义的版本,则使用用户自定义版本。如果没有用户自定义版本,则使用标准库的版本。

operator new系列函数与operator new[]系列函数的功能都是分配n个字节的内存,那它们没有区别吗?区别是有的。operator new分配单个对象,n不可能为0。而在C++中new type[0]是合法的,而且必须返回非空指针(但该指针不能解引用)。所以operator new[]系列函数要处理n==0的情况。而且,delete[]表达式是要对对象进行析构的,但delete[]表达式是如何知道有几个对象的?所以new[]在申请内存的时候要申请额外的内存来存储它申请的元素的个数,delete[]的时候按照规则来读就行了。

时间: 2024-11-05 18:58:39

C++ new、delete的相关文章

Linux Kernel Module(LKM) Init、Delete Code Principle Learning

目录 1. Linux模块(LKM)简介 2. 使用Linux模块 3. LKM模块加载原理 4. LKM模块卸载原理 1. Linux模块(LKM)简介 模块是一种向linux内核添加"设备驱动程序"."文件系统"."其他组件"的有效方法,而无须重新编译内核或重启系统,这消除了许多限制,同时带来了很多的优点 1. 通过使用模块,内核程序员能够预先编译大量驱动程序,而不会致使内核映像的尺寸发生膨胀.在自动检测硬件或用户提示后,安装例程会选择适当的

hbase源码系列(十一)Put、Delete在服务端是如何处理?

在讲完之后HFile和HLog之后,今天我想分享是Put在Region Server经历些了什么?相信前面看了<HTable探秘>的朋友都会有印象,没看过的建议回去先看看,Put是通过MultiServerCallable来提交的多个Put,好,我们就先去这个类吧,在call方法里面,我们找到了这句. responseProto = getStub().multi(controller, requestProto); 它调用了Region Server的multi方法.好,我们立即杀到HReg

数据库的update、delete、insert和select用法

String sql=null; 1.sql="update 表名 set <列名>=<表达式> [where=<表达式>]" 2.sql="delete from 表名 [where=<表达式>]" 3.sql="insert into 表名 [column_list] values(date_values)  [where=<表达式>]" 4.sql="select * f

hive增加Update、Delete支持

一.配置hive-site.xml二.建表三.操作四.总结 一.配置hive-site.xml CDH版本先进入Hive配置页 选择高级,找到hive-site.xml 的 Hive 客户端高级配置代码段配置项 点击+号,增加如下配置项 hive.support.concurrency = true hive.enforce.bucketing = true hive.exec.dynamic.partition.mode = nonstrict hive.txn.manager = org.a

sqlserver 大数据量的insert、delete操作优化

http://blog.csdn.net/lanyuzhen/article/details/7547476 --大批量导出orders表:insert DBCC DROPCLEANBUFFERS  DBCC FREEPROCCACHE goSET NOCOUNT ON BEGIN TRANSACTION  INSERT INTO test.dbo.orders with(tablock) SELECT * FROM bak.dbo.OrdersWHERE ordertime BETWEEN '

数据库中删除语句Drop、Delete、Truncate的相同点和不同点的比较

数据库中删除语句Drop.Delete.Truncate的相同点和不同点的比较(举例说明) 数据库删除语句的分别介绍:Delete:用于删除表中的行(注:可以删除某一行:也可以在不删除表的情况下(即意味着表的结构.属性.索引完整)删除所有行)                语法:删除某一行:Delete From 表名称  Where 列名称=值              删除所有行: Delete From 表名称       或     Delete *  From  表名称   Drop:

SQL Server DML(UPDATE、INSERT、DELETE)常见用法(一)

1.引言 T-SQL(Transact Structured Query Language)是标准的SQL的扩展,是程序和SQL Server沟通的主要语言. T-SQL语言主要由以下几部分组成: 数据定义语言(DDL):用来建立数据库.数据库对象等,如CREATE TABLE.DROP TABLE等. 数据控制语言(DCL):控制数据库的存取许可.权限等,如GRANT等. 数据操纵语言(DML):用于插入.修改.删除和查询数据库中数据,如SELECT.INSERT.UPDATE.DELETE等

Hive支持行级update、delete时遇到的问题

Hive从0.14版本开始支持事务和行级更新,但缺省是不支持的,需要一些附加的配置.要想支持行级insert.update.delete,需要配置Hive支持事务.(行级的insert好像不配置也能运行) 1.修改hive-site.xml,添加如下语句: <property> <name>hive.support.concurrency</name> <value>true</value> </property> <prope

oracle中drop、delete和truncate的区别

oracle中可以使用drop.delete和truncate三个命令来删除数据库中的表, 1. delete和truncate都是删除表中的内容而不能删除表的结构,而drop则是删除表的结构和内容(表将不复存在): 2. delete可以删除整个表的数据也可以有选择性地删除某一条或多条数据,而truncate则是一次性删除整个表的数据: 3. 使用delete删除的表数据并没有真正被删掉,数据占用的表空间还存在,相当于Windows中将数据删除到回收站中,日后有需要还可以恢复: 4. 使用tr