我的编程空间,编程开发者的网络收藏夹
学习永远不晚

C++中的opeartor new和placement new使用步骤

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

C++中的opeartor new和placement new使用步骤

new做了哪些:

在c++中,对new的调用时,new完成的工作通常是有以下几步:

调用operator new函数分配出内存待用对象的构造方法构造出对象返回该对象的指针

operator new
(1)只分配所要求的空间,不调用相关对象的构造函数。当无法满足所要求分配的空间时,则
->如果有new_handler,则调用new_handler,否则
->如果没要求不抛出异常(以nothrow参数表达),则执行bad_alloc异常,否则
->返回0
(2)可以被重载
(3)重载时,返回类型必须声明为void*
(4)重载时,第一个参数类型必须为表达要求分配空间的大小(字节),类型为size_t
(5)重载时,可以带其它参数

opeartor new重载测试

class X
{
public:
    X() { cout<<"constructor of X"<<endl;}
    ~X() { cout<<"destructor of X"<<endl;}
    void* operator new(size_t size,string str)
    {
        cout<<"operator new size "<<size<<" with string "<<str<<endl;
        return ::operator new(size);
    }

    void operator delete(void* pointee)
    {
        cout<<"operator delete"<<endl;
        ::operator delete(pointee);		//调用全局的 operator delete函数
    }
private:
    int num;
};

int main()
{
    X *px = new("A new") X;
    delete px;
    return 0;
}

// 输出结果
// operator new size 4 with string A new
// constructor of X
// destructor of X
// operator delete

那么为什么要重载operator new函数呢?首先第一点当然是因为new作为一种操作符是不能被重载的,而作为new中重要的一环:分配内存,重载operatir new就变的一种必要的操作了。全局opeartor new在分配内存时,实际上也是对malloc的一层包装,在进行大量次数的内存分配时容易出现内存碎片的问题,通过重载operator new函数可以自定的将内存分配在独立出来的一块内存区域,可以更高效率的实现内存分配的管理,同时也可以有效减少内存碎片化以及不易与管理的问题。

重载operator new函数还有很多的用途,比如,他可以帮助我们查找内存泄漏,在c++中,内存泄漏是痛中之痛,重载该函数并与宏定义相配合可以很好的检测出内存泄漏的地方在哪里。相关文章链接:https://www.jb51.net/article/41939.htm

placement new

placement new是operator new的一个重载版本,他的作用是可以将一个对象分配到指定的内存空间。实现代码如下:

void* operator new(std::size_t, void* __p) throw()
{
    return __p;
}

placement new 只是operator new的一个重载版本,只是起了一个别名而已.
代码示例:

class A{
    int num;
public:
    A(){
        cout<<"A's constructor"<<endl;
    }

    ~A(){
        cout<<"~A"<<endl;
    }
    void show(){
        cout<<"num:"<<num<<endl;
    }
};


int main()
{
	char* mem;
	cout << (void*)mem << endl;
	A* a = new(mem) A;
	cout << (void*)a << endl;
	return 0;
}

// 0x104e570ac
// A's constructor
// 0x104e570ac

阅读以上程序,注意以下几点。
(1)用定位放置new操作,既可以在栈(stack)上生成对象,也可以在堆(heap)上生成对象。如本例就是在栈上生成一个对象。

(2)使用语句A* p=new (mem) A;定位生成对象时,指针p和数组名mem指向同一片存储区。所以,与其说定位放置new操作是申请空间,还不如说是利用已经请好的空间,真正的申请空间的工作是在此之前完成的。

(3)使用语句A *p=new (mem) A;定位生成对象是,会自动调用类A的构造函数,但是由于对象的空间不会自动释放(对象实际上是借用别人的空间),所以必须显示的调用类的析构函数,如本例中的p->~A()。

(4)万不得已才使用placement new,只有当你真的在意对象在内存中的特定位置时才使用它。例如,你的硬件有一个内存映像的I/O记时器设备,并且你想放置一个Clock对象在哪那个位置。

在一些高效率的程序中,往往会开辟出一块独立的内存空间配合placement new来实现高效率的内存释放与配置,如在SGI STL的内存配置函数allocate 与 deallcate函数,以及大名鼎鼎的memory pool技术都很大程度上依靠了placement new定位创建对象。在快速的内存分配与释放的过程中这是一个非常实用的方法。

Placement new使用步骤

在很多情况下,placement new的使用方法和其他普通的new有所不同。这里提供了它的使用步骤。

第一步 缓存提前分配

有三种方式:

1.为了保证通过placement new使用的缓存区的memory alignment(内存队列)正确准备,使用普通的new来分配它:在堆上进行分配

class Task ;
char * buff = new [sizeof(Task)]; //分配内存
(请注意auto或者static内存并非都正确地为每一个对象类型排列,所以,你将不能以placement new使用它们。)

2.在栈上进行分配

class Task ;
char buf[N*sizeof(Task)]; //分配内存

3.还有一种方式,就是直接通过地址来使用。(必须是有意义的地址)

void* buf = reinterpret_cast<void*> (0xF00F);

第二步:对象的分配

在刚才已分配的缓存区调用placement new来构造一个对象。

Task *ptask = new (buf) Task

第三步:使用

按照普通方式使用分配的对象:

ptask->memberfunction();
ptask-> member;
//...

第四步:对象的析构

一旦你使用完这个对象,你必须调用它的析构函数来毁灭它。按照下面的方式调用析构函数:

ptask->~Task(); //调用外在的析构函数,显式调用!

第五步:释放

你可以反复利用缓存并给它分配一个新的对象(重复步骤2,3,4)如果你不打算再次使用这个缓存,你可以象这样释放它:

delete [] buf;

总结:

(1)若想在堆上建立一个对象,应该用new操作符。它既分配内存又调用其构造函数进行初始化。
(2)若仅仅想分配内存,应该调用operator new(),他不会调用构造函数。若想定制自己在堆对象被建立时的内存分配过程,应该重写自己的operator new()。
(3)若想在一块已经获得的内存空间上建立一个对象,应该用placement new。在实际开发过程中,这种写法一般在高性能高稳定场景下使用。本文主要是为了更好的理解STL源码中alloator的内存管理行为所写。

理解可能并不规范,表达也会有所纰漏。

参考文章:

https://cloud.tencent.com/developer/article/1177460

https://blog.51cto.com/u_15060533/4689267

https://www.cnblogs.com/luxiaoxun/archive/2012/08/10/2631812.html

到此这篇关于C++中的opeartor new和placement new详解的文章就介绍到这了,更多相关C++ opeartor new和placement new内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

C++中的opeartor new和placement new使用步骤

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

C++中的opeartor new和placement new使用步骤

这篇文章主要介绍了C++中的opeartor new和placement new详解,在很多情况下,placement new的使用方法和其他普通的new有所不同。这里提供了它的使用步骤,需要的朋友可以参考下
2022-11-13

c++中new和delete怎么使用

在C++中,new和delete是用来动态分配和释放内存的操作符。1. 使用new操作符动态分配内存:```int* p = new int; // 分配一个int类型的内存空间,并将其地址赋给指针p```在这个例子中,new操作符会在堆上
2023-09-27

C++中new和malloc的区别及使用

本篇内容介绍了“C++中new和malloc的区别及使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!定义上:malloc memory a
2023-06-04

c++中的new和delete怎么用

小编给大家分享一下c++中的new和delete怎么用,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!new expressionnew一个类型,会创建一个该类型的
2023-06-22

C++的new和delete使用示例详解

这篇文章主要为大家介绍了C++的new和delete使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2022-12-08

C++中new和delete匹配使用过程详解

关于new和delete的使用相信大家并不陌生,可是为什么使用new的时候要用delete,使用new[]的时候又要用delete[]呢?本文就来和大家详细说说
2023-02-14

C++中new类型的运算符怎么使用

这篇文章主要介绍“C++中new类型的运算符怎么使用”,在日常操作中,相信很多人在C++中new类型的运算符怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C++中new类型的运算符怎么使用”的疑惑有所
2023-06-29

你知道C++中new和delete为什么要匹配使用吗

关于new和delete的使用相信大家并不陌生,可是为什么使用new的时候要用delete,使用new[]的时候又要用delete[]呢?本文就来和大家详细说说
2023-01-10

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

这篇文章主要讲解了“C++中怎么使用new和delete进行动态内存分配与数组封装”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++中怎么使用new和delete进行动态内存分配与数组封装
2023-06-29

C++封装静态链接库和使用的详细步骤

这篇文章主要介绍了C++封装静态链接库和使用,本文描述了怎么去把一个C++程序封装成一个静态库并且如何去使用这些静态库,需要的朋友可以参考下
2022-11-13

vue3中使用vuex和vue-router的详细步骤

这篇文章主要介绍了vue3中使用vuex和vue-router的步骤,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
2022-12-08

Linux中使用Systemd和Crontab实现日志轮转的方法和步骤

在Linux中,可以使用Systemd和Crontab来实现日志轮转。下面是使用这两个工具来实现日志轮转的方法和步骤:使用Systemd实现日志轮转的步骤:1. 创建一个Systemd服务单元文件,例如`/etc/systemd/syste
2023-10-09

C++技术中的机器学习:使用C++构建机器学习模型的步骤是什么?

c++++ 是构建机器学习模型的理想选择。构建模型的步骤包括:数据收集和预处理、模型选择、模型训练、模型评估和模型部署。实战案例演示了使用 mlpack 库构建线性回归模型的过程,包括数据加载、模型训练、保存、加载和预测。C++ 技术中的机
C++技术中的机器学习:使用C++构建机器学习模型的步骤是什么?
2024-05-12

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录