C++基础——new与delete
本文目录
专业名称
new operator:new操作符,new表达式
operator new:new运算符
placement new:定位new
delete operator:delete操作符,delete表达式
operator delete:delete运算符
delete没有placement版本 各个版本的解释 1. new operator
new operator:new表达式
实际上只是一个称呼,是三个操作的集合。
- 申请内存(调用operator new)
- 在内存上调用构造函数
- 将申请的内存空间返回
delete operator:delete表达式
delete operator也是一个称呼,是两个操作的集合。
- 调用析构函数
- 调用operator delete释放空间
operator new/delete:new/delete运算符
- 分为::operator new与Class::operator new。一个是全局的,一个是类内部定义的。平时听到的new与delete重载,就是重载这里的new/delete。注意点如下。
-- class中的new与delete是隐式静态的。也就是不管你有没有声明为static,它都是static的。
-- 非static成员在没有实例存在的情况下是不能使用的。而当我们定义一个实例时,很明显此时实例还没有存在,这个时候不可能调用一个非static的成员,所以operator new/delete必须是static的。
-- static成员是不会隐式传入this指针的,所以在operator new/delete中不能使用任何类的非静态成员。
-- 非静态的成员函数在编译器会在argument list的第一个位置插入一个本身类型的this指针。所以一个函数名,参数列表与全局函数一模一样的函数,也不会出现二义性问题。但是一个static成员函数,是不会隐私插入this指针的,所以当我们在class中重载new/delete时,客户定义实例时需要确认是否在全局也定义了new,否则会产生二义性。举个栗子。
//VS2013
class StringClass
{
public:void *operator new(size_t size);
};
void *operator new(size_t size);
void main()
{//1. 调用operator new申请内存//2. 调用构造函数//二义性,同时存在两个可用的operator newStringClass *p = new StringClass;
}
-- PS:关于函数匹配规则,一开始接触觉得很简单,当某天触发了bug的时候就会“书到用时方恨少”,这方面推荐两个连接给大家。看这里,还有这里
- 关于operator new/delete标准库提供了8个版本,这些版本的new/delete我们都是可以重载的。如下。
//八个版本中有2个new版本有可能抛出异常
void* operator new(size_t t);
void* operator new[](size_t t);
void* operator delete(void*)noexcept;
void* operator delete[](void*)noexcept;//nothrow_t为空结构体,用于区分上面与下面运算符
void* operator new(size_t t,nothrow_t&)noexcept;
void* operator new(size_t t,nothrow_t&)noexcept;
void* operator delete(void *,nothrow_t&)noexcept;
void* operator delete[](void *,nothrow_t&)noexcept;
理论这么多,下面先来个栗子。
//StringClass.h
//自己定义的一个类
#pragma once
#include<iostream>
using namespace std;
class StringClass
{
public:StringClass(){cout << "string class construtor" << endl;}~StringClass(){cout << "string class destrutor" << endl;}void *operator new(size_t size){cout << "Class::operator new(size_t) " << size << endl;void *ret = (void*)malloc(size);return ret;}static void operator delete(void *p){free(p);cout << "Class::operator delete(void*)" << endl;}
};
void main(){StringClass *p = new StringClass;delete p;
}
结果如下。在new表达式中,先调用了operator new,再调用constructor,最后将指针返回给p。最后在释放的时候,先调用了destructor,再调用了operator delete。
既然使用到了delete,怀着“授人以鱼不如授人以渔”的想法,推荐读者了解一下crtdbg这个头文件,谷歌一下就知道了。
placement new:定位new
- 在堆里面申请内存,需要寻找空的内存,多次申请释放还会产生大量的内存碎片,但这个神器会帮你解决这些问题。使用它,你只需要申请一次内存,就能够多次创建不同的实例,具体参见下例的讲解。
- 前面提到,new operator会有三个步骤,第一是申请内存,第二是调用构造函数,第三是返回指针。定位new,之所以为定位,是因为我们事先分配好了内存,并且指定了必须使用这块内存进行初始化。共有四种语法如下。
new (place_address) type;
new (place_address) type (initializers);
new (place_address) type[size];
new (place_address) type[size]{braced initializers list};
对第一种我们举个栗子。
#pragma once
#include<iostream>
using namespace std;class StringClass
{
public:StringClass(){cout << "string class construtor" << endl;}~StringClass(){cout << "string class destrutor" << endl;}//比起前面的代码,增添了这个函数static void *operator new(size_t size, void *p) {cout << "Class::operator new(size_t,void*)" << endl;return p;}
};void main()
{StringClass *buf = (StringClass*)malloc(sizeof(StringClass));memset(buf, 0, sizeof(StringClass));StringClass *p2 = new(buf) StringClass();p2->~StringClass();free(buf);
}
- 上面总共有五个步骤:
-- 上述代码先使用申请了一块内存,大小用户根据自己需要去决定。
-- 初始化这块内存。
-- 然后在上面调用了StringClass的构造函数,再令p2指向他。
-- 然后p2使用完毕在上面调用自己的析构函数。
-- 程序结束前将这块内存释放。假如有需要创建另外一个对象,我们可以不用申请新的内存,继续使用这块内存。
- 与operator new不同的是,使用placement new是无需定义operator delete的,如上,整个过程压根就没有用到它。相反,假如你在客户端使用了它,还会导致调用析构函数的多次调用。
警告
除了placement new外,其他版本的new与delete都要成对地重载。因为你重载了编译器的new,它不知道delete需要为你做些什么。
总结
- new总共分成3类,new operator是一个操作的集合,不是具体的运算符。可以重载的叫做operator new。
- 使用了placement new,必须定义void operator new(siez_t,void p),不用定义operator delete。而除了placement new,若定义了operator new/delete需要成对定义。
- 所有的operator new都是隐式静态的,为了让代码易于阅读,你应该加上static
- 所有的operator new都应该返回void*
最后的疑问
在很多书籍以及博客中,都指出了下面这个operator new不能被重载。在C++Primer第五版,白色封面的那本,P727最下方中,明确指出了它不能重载,但实际上,使用placement new的时候我们却不得不重载这个版本。关于这一点,希望有高人能够给出意见。
转载于:https://www.cnblogs.com/suimeng/p/5295754.html
C++基础——new与delete相关推荐
- SQL Server 2012入门T-SQL基础篇:(8)Delete语句
基本的语法格式如下: Deleteform表名 [where条件语句] 此语句将删除表的部分或者全部记录; (1)带WHERE条件子句,将删除符合条件的记录: 可以看到已经删除了"Emplo ...
- 《零基础》MySQL DELETE 语句(十五)
语法 以下是 SQL DELETE 语句从 MySQL 数据表中删除数据的通用语法: DELETE FROM table_name [WHERE Clause] 如果没有指定 WHERE 子句,MyS ...
- C++基础new和delete运算符,new和delete简介
在C语言中,动态分配内存用 malloc() 函数,释放内存用 free() 函数.如下所示: int p = (int) malloc( sizeof(int) * 10 ); //分配10个int ...
- python tkinter insert函数_Python3 tkinter基础 Entry insert delete 点击按钮 向输入框赋值 或 清空...
? ???????Python : 3.7.0 ?????????OS : Ubuntu 18.04.1 LTS ????????IDE : PyCharm 2018.2.4 ??????Conda ...
- python entry如何清空_Python3 tkinter基础 Entry insert delete 点击按钮 向输入框赋值 或 清空...
Python : 3.7.0 OS : Ubuntu 18.04.1 LTS IDE : PyCharm 2018.2.4 Conda : 4.5.11 typesetting : Markdown ...
- python删除列表元素delete_Python3 tkinter基础 Listbox delete 删除单个、所有元素
Python : 3.7.0 OS : Ubuntu 18.04.1 LTS IDE : PyCharm 2018.2.4 Conda : 4.5.11 typesetting : Markdown ...
- 关于delete和delete[]
[精彩] 求问delete和delete[] 的区别?? http://www.chinaunix.net/jh/23/311058.html C++告诉我们在回收用 new 分配的单个对象的内存空间 ...
- mysql核心数据库_从MySQL基础进军MySQL核心架构 178集MySQL数据库核心基础视频教程 MySQL基础案例教程...
从MySQL基础进军MySQL核心架构 178集MySQL数据库核心基础视频教程 MySQL基础案例教程 课程目录 (1) 01MySQL基础_课程引入.avi (2) 02MySQL基础_为什么学习 ...
- Linux下MySQL基础使用命令
www.mysql.com 官方网站 communlty server 社区版 免费的 显示系统自带的mysql包 yum list | grep mysql 安装mysql: yum instal ...
- MySQL数据库 学习笔记 零基础入门 面试 整理
一.MySQL基础篇 1. 数据库技术的基本概念和方法 1.1 数据库基本概念 1] 数据 数据(Data)指对客观事物进行描述并可以鉴别的符号,这些符号是可识别的.抽象的,不仅仅指狭义上的数字,而是 ...
最新文章
- ios游戏开发 Sprite Kit教程:初学者 2
- golang表单及验证支持
- 用c#开发微信(1)服务号的服务器配置和企业号的回调模式 - url接入
- 利用nodeJs anywhere搭建本地服务器环境
- Android入门教程免费获取
- 二维矩阵中的最大矩形面积--java实现
- mysql如何获取句柄_关于获取进程句柄的问题
- 如何用Vue实现简易的富文本编辑器,并支持Markdown语法
- JAVAWEB入门之IDEA与tomcat相关配置
- mysql hang_mysql hang
- ajax数据显示,使用js通用模板
- 九度OJ 1207 质因数的个数
- php如何去除字符串中的空格,php如何去除字符串中的空格
- 操作系统原理学习总结
- oracle数据库if函数,Oracle NULLIF函数
- NATAPP内网穿透使用
- GPFS实施方案的思考
- 北航计算机学院考研专硕,北京航空航天大学计算机学院2020考研拟录取及未录取名单...
- 微信小程序实现倒计时功能(超简单)
- 基于php教师档案管理系统毕业设计