本文目录

专业名称

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相关推荐

  1. SQL Server 2012入门T-SQL基础篇:(8)Delete语句

    基本的语法格式如下: Deleteform表名 [where条件语句] 此语句将删除表的部分或者全部记录; (1)带WHERE条件子句,将删除符合条件的记录: 可以看到已经删除了"Emplo ...

  2. 《零基础》MySQL DELETE 语句(十五)

    语法 以下是 SQL DELETE 语句从 MySQL 数据表中删除数据的通用语法: DELETE FROM table_name [WHERE Clause] 如果没有指定 WHERE 子句,MyS ...

  3. C++基础new和delete运算符,new和delete简介

    在C语言中,动态分配内存用 malloc() 函数,释放内存用 free() 函数.如下所示: int p = (int) malloc( sizeof(int) * 10 ); //分配10个int ...

  4. python tkinter insert函数_Python3 tkinter基础 Entry insert delete 点击按钮 向输入框赋值 或 清空...

    ? ???????Python : 3.7.0 ?????????OS : Ubuntu 18.04.1 LTS ????????IDE : PyCharm 2018.2.4 ??????Conda ...

  5. 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 ...

  6. 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 ...

  7. 关于delete和delete[]

    [精彩] 求问delete和delete[] 的区别?? http://www.chinaunix.net/jh/23/311058.html C++告诉我们在回收用 new 分配的单个对象的内存空间 ...

  8. mysql核心数据库_从MySQL基础进军MySQL核心架构 178集MySQL数据库核心基础视频教程 MySQL基础案例教程...

    从MySQL基础进军MySQL核心架构 178集MySQL数据库核心基础视频教程 MySQL基础案例教程 课程目录 (1) 01MySQL基础_课程引入.avi (2) 02MySQL基础_为什么学习 ...

  9. Linux下MySQL基础使用命令

    www.mysql.com 官方网站 communlty server 社区版  免费的 显示系统自带的mysql包 yum list | grep mysql 安装mysql: yum instal ...

  10. MySQL数据库 学习笔记 零基础入门 面试 整理

    一.MySQL基础篇 1. 数据库技术的基本概念和方法 1.1 数据库基本概念 1] 数据 数据(Data)指对客观事物进行描述并可以鉴别的符号,这些符号是可识别的.抽象的,不仅仅指狭义上的数字,而是 ...

最新文章

  1. ios游戏开发 Sprite Kit教程:初学者 2
  2. golang表单及验证支持
  3. 用c#开发微信(1)服务号的服务器配置和企业号的回调模式 - url接入
  4. 利用nodeJs anywhere搭建本地服务器环境
  5. Android入门教程免费获取
  6. 二维矩阵中的最大矩形面积--java实现
  7. mysql如何获取句柄_关于获取进程句柄的问题
  8. 如何用Vue实现简易的富文本编辑器,并支持Markdown语法
  9. JAVAWEB入门之IDEA与tomcat相关配置
  10. mysql hang_mysql hang
  11. ajax数据显示,使用js通用模板
  12. 九度OJ 1207 质因数的个数
  13. php如何去除字符串中的空格,php如何去除字符串中的空格
  14. 操作系统原理学习总结
  15. oracle数据库if函数,Oracle NULLIF函数
  16. NATAPP内网穿透使用
  17. GPFS实施方案的思考
  18. 北航计算机学院考研专硕,北京航空航天大学计算机学院2020考研拟录取及未录取名单...
  19. 微信小程序实现倒计时功能(超简单)
  20. 基于php教师档案管理系统毕业设计

热门文章

  1. 第二章 传送与交换作业
  2. JAVA中构造方法说法_关于Java程序的构造方法,说法错误的是( )
  3. keras ImageDataGenerator数据增强
  4. 论文笔记 | 使用GCN建模关系数据
  5. 搜索引擎技术在仿冒网站检测中的应用
  6. 20170908算法工程师在线笔试之jd编程思路
  7. python求解LeetCode 习题 Excel Sheet Column Title
  8. pytorch 存取模型(待补充)
  9. oracle中常用的方法,oracle常用方法
  10. 测试nb信号的软件_NB频点概述