首页 > 其他分享 >重载全局的new和delete

重载全局的new和delete

时间:2024-04-16 22:46:09浏览次数:18  
标签:Foo void operator 重载 new delete size

重载全局的new和delete

::operator new ::operator new[] -> 不可以被声明与同一个namespace之内

new会执行三个动作: -> 之前的代码提到:

  • new本身会开辟内存空间.所以声明方法需要一个size_t size的参数

    • inline void* operator new(size_t size) {}

::operator delete ::operator delete[] -> 不可以被声明与同一个namespace之内

  • delete本身是归还内存的动作.所以需要接收一根指针

    • inline void operator delete(void* ptr) {}

上述内容示例代码:

#pragma
#ifndef __NEW_DELETE__
#define __NEW_DELETE__

#include <Windows.h> // 通常来说上面还需要一个宏文件来声明这些不变的系统宏
#include <iostream>

namespace MyDefinition {
void* MyAlloc(size_t size) {
return malloc(size);
}

void MyFree(void* ptr) {
return free(ptr);
}

/* 下面两个操作符重载不能声明在一个namespace当中 -> 因为调用的是全局的 */
void* operator new(size_t size) {
std::cout << "MyAlloc global new() \n";
return MyDefinition::MyAlloc(size);
}

//void* operator new[](size_t size) {
//std::cout << "MyAlloc global new() \n";
//return MyDefinition::MyAlloc(size);
//}

void operator delete(void* ptr) {
std::cout << "MyFree global delete() \n";
return MyDefinition::MyFree(ptr);
}

//void operator delete[](void* ptr) {
//std::cout << "MyFree global delete() \n";
//return MyDefinition::MyFree(ptr);
//}
}

#endif // !__NEW_DELETE__

上述是全局的重载

class当中的重载

#pragma
#ifndef __CLASS_NEW_DELETE__
#define __CLASS_NEW_DELETE__

#include <iostream>
#include <Windows.h>

class Foo
{
public:
Foo() {}
// ~Foo() { delete(this); } // 这样声明则会删除指针而不是指针指向的对象
void* operator new(size_t);
void operator delete(void*, size_t);
};

inline void* Foo::operator new(size_t size) {
/* 开辟一块内存空间.返回指针 */
return malloc(size);
}

inline void Foo::operator delete(void* ptr, size_t size) {
free(ptr);
}

#endif // !__CLASS_NEW_DELETE__

调用代码:

#include "new_delete_class.hpp"

int main() {
Foo* p = new Foo();
/*
* new这个动作会做三件事
* 1、声明一根指针.调用自己的new(操作符重载)方法开辟一块内存区域
* 2、将自己的方法指针静态转型为指向Foo的指针
* 3、通过指针调用Foo的构造函数
* try {
* void* mem = operator new(sizeof(Foo));
* p = static_cast<Foo*>(mem);
* p->Foo::Foo(); // 通过指针调用Foo的构造函数
* }
* 可以看到现有内存空间才有的类的构造函数调用
*/
delete p;
/*
* 做两件事情
* 1、通过指针去调用Foo类的析构函数
* 2、通过操作符重载释放掉指针空间
* p->~Foo();
* operator delete(p)
*/
}

另一种操作符重载:

#pragma
#ifndef __CLASS_NEW_DELETE__
#define __CLASS_NEW_DELETE__

#include <Windows.h>

class Foo
{
public:
Foo();
void* operator new[](size_t); // 传入数组
void operator delete[](void*, size_t);
};

inline void* Foo::operator new[](size_t size) {
return malloc(size);
}

inline void Foo::operator delete[](void* ptr, size_t size) {
free(ptr);
}

#endif // !__CLASS_NEW_DELETE__

调用代码:

#include "new_delete_class_more.hpp"

int main() {
Foo* f = new Foo[10]; // 调用10次构造函数 -> 也会开辟10块内存空间

delete[10] f; // 调用10次析构函数
}

上述代码可以看到new这个动作会被分解为三个动作,会回到类当中寻找定义好的代码

强制调用全局的示例代码:

#include "new_delete_class_more.hpp"

int main() {
Foo* fp = ::new Foo;
::delete fp;
/*
* 加了"::"的声明以后会强制调用全局的new和delete
* 如果Foo当中没有定义new和delete也会调用全局的
*/
}

整体类设计示例:

#pragma
#ifndef __CLASS_NEW_DELETE_REAL__
#define __CLASS_NEW_DELETE_REAL__

#include <iostream>
#include <Windows.h>
#include <string>

class Foo
{
public:
Foo(): _id(0) {}
Foo(int i): _id(i) {}

~Foo() {}

/* 新建一个hpp文件创建一块命名空间提供实现 */
static void* operator new(size_t);
static void operator delete(void*, size_t);
static void* operator new[](size_t);
static void operator delete[](void*, size_t);
public:
   /* 下面三个成员变量就是类的大小 */
int _id;
long _data;
std::string _str;
};

#endif // !__CLASS_NEW_DELETE_REAL__

注意:

  • 上述代码当中调用了很多次的构造函数,那么实际开辟内存区域的时候变量size_t的大小会多一个int类型数据大小 (counter计数器)-> 该数据的值是调用的构造函数的次数

  • this指针调用构造函数从counter近的开始.析构函数从举例counter远的开始 -> 这里没有画栈空间图所以口语化表达

可以重载全局、可以重载局部、还可以重载new() -> 注意newnew()的区别 -> 并不是构造方法

重载new()delete() -> 不要和构造函数混淆

特点:

  • 每一个版本的new()的参数列都是独一无二

  • 第一个参数固定是size_t -> 知道类的大小 -> 如果不是编译会报错

  • 其余的参数以new指定的placement arguments为初值

delete():

  • 也可以重载

  • 只有当重载的new()调用构造函数抛出异常的时候(new这个动作被拆解成三步)才会调用这些重载的delete()

  • 主要用来归还未能完全创建成功的object所占用的memory

示例代码:

#pragma
#ifndef __NEW()_DELETE()__
#define __NEW()_DELETE()__

class Foo
{
public:
Foo();
void* operator new(size_t);
void* operator new(size_t, void* star);
void* operator new(size_t, long extra);
void* operator new(size_t, long extra, char init);

/* 重载对于的delete -> 注意这些重载的delete调用的时机 */
void operator delete(void* star); // 一般的delete -> 对应上面第一个new
void operator delete(void*, void*); // 对应上面第二个 -> 第一个void*参数是默认的delete自带的
void operator delete(void*, long); // 对应上面第三个
void operator delete(void*, long, char); // 对应上面第四个
};

#endif // !__NEW()_DELETE()__

调用字符串的new() -> 如Foo * p = new(size) Foo的操作.会返回计数器+size大小的内容 -> 内存模型,拿到的其实是一根指针

  • 这样就实现了悄无声息的多分配一些空间 -> 不仅仅是一根指针大小的空间

  •  

     

标签:Foo,void,operator,重载,new,delete,size
From: https://www.cnblogs.com/JunkingBoy/p/18139448

相关文章

  • 关于post、get、put、delete的区别
    post和put的区别put和post操作都是向服务器端发送数据,但是put是幂等的,而post是非幂等的。所谓幂等,即多次发送同一个请求时候,产生的结果是一样的就是幂等性原则,这是为了当网络出现延迟等,服务器(客户端)之间发送请求没有收到回应,再重新发一次,实际上另一端已经接收到了第一次的请求,接......
  • C++动态内存分配/malloc/new
    0前言这部分确实是面试老八股了,不过我还是记录一下1内存分区在C语言中,将内存分为程序代码区+数据区,其中数据区又分为静态存储区和动态存储区在C++中,分为五种:动态存储区:栈区:存放局部变量,由编译器自动分配释放,程序员不能操作堆:由程序员使用malloc/new申请,用free/delete......
  • MySQL 中 DELETE 语句中可以使用别名么?
    1情境deletefromtest1t1wherenotexists(select1fromtest2t2wheret1.id=t2.id);以上sql报错:ERROR1064(42000):YouhaveanerrorinyourSQLsyntax;checkthemanualthatcorrespondstoyourMySQLserverversionfortherightsyntaxtouse......
  • SystemVerilog -- 2.1 Data Types ~ New Data types
    SystemVeriloglogicandbit在上一篇文章中,概述了主要数据类型。在本会话中,我们将研究4-state和2-state变量以及两种名为logic和bit的新数据类型。4-statedatatypes除了0和1之外,还可以具有未知(X)和高阻态(Z)值的类型称为4态类型。请注意,只能在过程快中驱动,例如,数据类......
  • Object.defineProperty 和new Proxy深度检测
    <!DOCTYPEhtml><htmllang="en"><head> <metacharset="UTF-8"> <metahttp-equiv="X-UA-Compatible"content="IE=edge"> <metaname="viewport"content="width=device......
  • Newman下载安装
    1.安装node.js安装步骤查看已安装版本node-v  2.安装Newman运行命令:npminstall-gnewman,即可完成安装操作。或者npminstall-gnewman--registry=http://registry.npm.taobao.org 检验当前Newman是否安装成功,在dos中输入命令:newman--version windows......
  • Linux云服务器文件删除恢复方法命令extundelete工具testdisk使用
    如果不小心删除了系统盘的文件,尤其是使用了rm-rf*,请立即停止对磁盘的写入,并且使用数据恢复软件进行恢复(下文有详细的步骤)。立即停止对磁盘的写入实际情况可能没那么容易。服务器可能是云服务器也可能是物理机,下面是可能的情况以及操作方法:1、云服务器:立即去控制台创建快照(防......
  • 读论文-新闻推荐系统:近期进展、挑战与机遇的评述(News recommender system_ a review
    前言今天读的论文为一篇于2022年发表在"人工智能评论"(ArtificialIntelligenceReview)的论文,文章主要强调了NRS面临的主要挑战,并从现有技术中确定了可能的解决方案。引用这篇论文:[1]Raza,Shaina,andChenDing."Newsrecommendersystem:areviewofrecentprogress,c......
  • 内存管理new and delete(C++)
        在本篇中,将会较为详细的介绍在Cpp中的两个新操作符new和delete,将会介绍其中的底层原理,以及这两个操作符的使用方法。其中还介绍了new/delete操作符使用的细节,还扩展了一些有关定位new表达式的知识点。最后总结了malloc/free与new/delete的区别。目......
  • CF1913B Swap and Delete 题解
    翻译给定一个字符串\(s\),你有两种操作:删除一个字符。(花费一枚金币)交换某两个字符的位置。(不花费金币)假设经过若干次操作后得到的字符串为\(t\)。\(t\)是好的当且仅当对于任意的\(i\)(\(1\lei\le|t|\),\(|t|\)为字符串\(t\)的长度),均满足\(t_i\nes_i\)。(\(s\)是......