当前位置: 首页 > news >正文

C++中的new、operator new与placement new

new operator

new operator是我们常用的new。

new 和 delete 是用来在 堆上申请和释放空间的 ,是 C++ 定义的 关键字,和 sizeof 一样。

实际 new / delete 和 malloc / free 最大的区别是,前者对于 自定义类型 除了可以开辟空间,还会调用构造和析构函数

  1. 分配内存,如果类A重载了operator new,那么将调用A::operator new(size_t )来完成,如果没有重载,就调用::operator new(size_t ),即全局new操作符来完成

  2. 调用构造函数生成类对象;

  3. 返回相应指针

1.operator new、operator delete就是对malloc和free的封装

2.operator new中调用malloc开辟空间失败后,改为抛异常处理,这种处理更符合C++处理错误的方式

new 的原理

Ⅰ. 调用 operator new 函数申请空间

Ⅱ. 在申请的空间上执行构造函数,完成对象的构造

delete 的原理

Ⅰ. 在空间上执行析构函数,完成对象中资源的清理工作

Ⅱ. 调用 operator delete 函数释放对象的空间

new T[N] 的原理

Ⅰ. 调用 operator new[] 函数,在 operator new[] 中实际调用 operator new 函数完成 N 个对象空间的申请

Ⅱ. 在申请的空间上执行 N 次构造函数

delete[] 的原理

Ⅰ. 在释放的对象空间上执行 N 次析构函数,完成 N 个对象中资源的清理

Ⅱ. 调用 operator delete[] 释放空间,实际在 operator delete[] 中调用 operator delete 来释放空间

operator new

operator new是一个操作符,和+ -操作符一样,作用是分配空间。我们可以重写它们,修改分配空间的方式。

operator new返回值必须是void*。第一个参数必须是size_t

void* operator new (std::size_t size) throw (std::bad_alloc);  
void* operator new (std::size_t size, const std::nothrow_t& nothrow_constant) throw(); 

在下面的例子中,我们使用重载了三个operator new方法, 并分别调用。

#include <iostream>
#include <string>
#include <malloc.h>
using namespace std;//student class
class Stu
{
public:Stu(string name, int age){cout << "call Stu class constructor" << endl; name_ = name;age_ = age;};
public:void print() const{cout << "name = " << name_ << std::endl;cout<< "age = " << age_ << std::endl;};void* operator new(size_t size){std::cout << "call operator new" << std::endl;return malloc(size);}void* operator new(size_t size, int num){std::cout << "call operator new with int" << std::endl;return malloc(size);} void* operator new(size_t size, char c){std::cout << "call operator new with char" << std::endl;return malloc(size);}      
private:string name_;int age_;
};
int main()
{Stu* stu1 = new Stu("a", 10);Stu* stu2 = new(1) Stu("a", 10);Stu* stu3 = new('c') Stu("a", 10);
}

placement new

placement new是operator new的一种重载形式,其作用是可以在指定的内存地址创建对象。

placement new返回值必须是void*。第一个参数必须是size_t, 第二个参数是void*。

void* operator new (std::size_t size, void* ptr) throw();

下面的是一个关于placement new的调用例子:

#include <iostream>
#include <string>
#include <malloc.h>
using namespace std;//student class
class Stu
{
public:Stu(string name, int age){name_ = name;age_ = age;};
public:void print() const{cout << "name = " << name_ << std::endl;cout<< "age = " << age_ << std::endl;};void* operator new(size_t size, void* p){std::cout << "placement new" << std::endl;return p;};    
private:string name_;int age_;
};
int main()
{void* stu1 = (Stu*)malloc(sizeof(Stu));new (stu1) Stu("stu1", 10);((Stu*)stu1)->print();
}

由于placement new可以在一个指定的位置创建对象,因此在STL中有很广泛的运用, 例子vector容器初始化的时候,会使用allocator申请一定的内存,当使用push_back放入对象时, 就可以使用placement new在申请的位置创建对象。

结论

对于new, operator new 和 placement new三者的区别, 我们总结如下:

new:

new是一个关键字,不能被重载。

new 操作符的执行过程如下:

  • 调用operator new分配内存 ;

  • 调用构造函数生成类对象;

  • 返回相应指针。

operator new:

operator new就像operator + 一样,是可以重载的。

如果类中没有重载operator new,那么调用的就是全局的::operator new来完成堆的分配。

同理,operator new[]、operator delete、operator delete[]也是可以重载的。

placement new:

placement new和operator new并没有本质区别。它们都是operator new操作符的重载,只是参数不相同。

placement并不分配内存,只是返回指向已经分配好的某段内存的一个指针。因此不能删除它,但需要调用对象的析构函数。

如果你想在已经分配的内存中创建一个对象,使用new时行不通的。

也就是说placement new允许你在一个已经分配好的内存中(栈或者堆中)构造一个新的对象。原型中void* p实际上就是指向一个已经分配好的内存缓冲区的的首地址。

相关文章:

C++中的new、operator new与placement new

new operator new operator是我们常用的new。 new 和 delete 是用来在 堆上申请和释放空间的 &#xff0c;是 C 定义的 关键字&#xff0c;和 sizeof 一样。 实际 new / delete 和 malloc / free 最大的区别是&#xff0c;前者对于 自定义类型 除了可以开辟空间&#xff0c;…...

ElasticSearch之cat anomaly detectors API

curl -X GET "https://localhost:9200/_cat/ml/anomaly_detectors?vtrue&pretty" --cacert $ES_HOME/config/certs/http_ca.crt -u "elastic:ohCxPHQBEs5*lo7F9"执行结果输出如下&#xff1a; curl -X GET "https://localhost:9200/_cat/ml/ano…...

Luminar Neo1.16.0(ai智能图像处理)

Luminar Neo是一款ai智能图像编辑软件&#xff0c;它专注于使用人工智能技术来实现对照片的快速、高效和创造性的编辑。 具体来说&#xff0c;Luminar Neo可以自动移除景观或旅行照片中令人分心的元素&#xff0c;例如电话线、电线杆等&#xff0c;从而增强照片的整体质量。同…...

ElasticSearch之cat aliases API

执行aliases命令&#xff0c;如下&#xff1a; curl -X GET "https://localhost:9200/_cat/aliases?pretty&vtrue" --cacert $ES_HOME/config/certs/http_ca.crt -u "elastic:ohCxPHQBEs5*lo7F9"执行结果输出如下&#xff1a; alias index …...

bash编程 数组和for循环的应用

bash编程 数组和for循环的应用 1、问题背景2、bash 定义数组3、for循环遍历输出数组所有元素4、编写bash脚本输出每个端口是否在监听状态 1、问题背景 linux服务器开机后&#xff0c;需要检查一组端口是否在监听&#xff0c;以便判断这些端口对应的服务是否在运行。可以考虑使…...

Python基础:标准库概览

1. 标准库介绍 Python 标准库非常庞大&#xff0c;所提供的组件涉及范围十分广泛&#xff0c;正如以下内容目录所显示的。这个库包含了多个内置模块 (以 C 编写)&#xff0c;Python 程序员必须依靠它们来实现系统级功能&#xff0c;例如文件 I/O&#xff0c;此外还有大量以 Pyt…...

C#,《小白学程序》第三课:类class,类的数组及类数组的排序

类class把数值与功能巧妙的进行了结合&#xff0c;是编程技术的主要进步。 下面的程序你可以确立 分数 与 姓名 之间关系&#xff0c;并排序。 1 文本格式 /// <summary> /// 同学信息类 /// </summary> public class Classmate { /// <summary> /…...

建筑结构健康监测系统和传统人工监测的区别

在繁华的城市里&#xff0c;建筑结构作为城市生命线的重要一环&#xff0c;其安全与稳定对城市的运转和居民的生活至关重要。为了更好地守护建筑结构的健康&#xff0c;WITBEE万宾自主研发建筑结构健康监测系统让建筑安全&#xff0c;在上一个台阶。 WITBEE万宾建筑结构健康监测…...

二 使用GPIO的复用功能 利用USART 实现printf()

参考这篇&#xff1a; STM32串口通信详解 1. 关于USART USART ( universal synchronous / asynchronous receiver /transmitter) 是一种串行通讯协议 , 允许设备通过串行端口进行数据传输&#xff0c; USART 能够以同步或者异步的方式进行工作&#xff0c;在实际的运用中&…...

C#中的警告CS0120、CS0176、CS0183、CS0618、CS0649、CS8600、CS8601、CS8602、CS8604、CS8625及处理

目录 一、CS0120 二、CS0176 1.解决前 2.解决后 3.解决办法 三、CS0183 四、CS0618 五、CS8600 六、CS8602 七、CS8622 1. 解决前&#xff1a; 2. 解决后&#xff1a; 3.解决方法&#xff1a; 八、CS8604和CS8625 九、CS0649 十、CS8601 一、CS0120 严重性 代…...

js中声明变量的关键字(const,let,var)

const 特点&#xff1a; const不允许在同一作用域重复声明&#xff0c;块级作用域暂时性死区&#xff0c;在声明之前&#xff0c;该变量是不可用的const声明的是一个只读变量&#xff0c;声明之后不能改变其值&#xff0c;一旦声明必须初始化但是const定义的对象属性是可以修…...

Android13 launcher循环切页

launcher 常规切页&#xff1a;https://blog.csdn.net/a396604593/article/details/125305234 循环切页 我们知道&#xff0c;launcher切页是在packages\apps\Launcher3\src\com\android\launcher3\PagedView.java的onTouchEvent中实现的。 1、滑动限制 public boolean onT…...

Java学习路线第一篇:Java基础(2)

这篇则分享Java学习路线第一part&#xff1a;Java基础&#xff08;2&#xff09; 从看到这篇内容开始&#xff0c;你就是被选定的天命骚年&#xff0c;将承担起学完Java基础的使命&#xff0c;本使命为单向契约&#xff0c;你可选择YES或者选择YES。 具体路线安排&#xff1a…...

网络工程师精华篇,50种网络故障及解决方法大集合

上午好&#xff0c;我的网工朋友。 做网络工程师&#xff0c;自然离不开网络&#xff0c;而日常工作中能搞多少大项目&#xff1f;最常见的其实还是网络故障的处理了。 怎么最高效地排查网络故障&#xff1f;怎么简单几招通网&#xff1f; 今天就从基础的入手&#xff0c;分…...

Unity播放网络视频

using System.Collections; using System.Collections.Generic; using UnityEngine; using Mx.UI; using Mx.Utils; using UnityEngine.UI; using UnityEngine.Video; /// <summary> 视频UI面板 </summary> public class VideoUIForm : BaseUIForm { private …...

SCI一区级 | Matlab实现GWO-CNN-LSTM-selfAttention多变量多步时间序列预测

SCI一区级 | Matlab实现GWO-CNN-LSTM-selfAttention多变量多步时间序列预测 目录 SCI一区级 | Matlab实现GWO-CNN-LSTM-selfAttention多变量多步时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab实现GWO-CNN-LSTM-selfAttention灰狼算法优化卷积长短…...

线性分类器--图像表示

整个模型 图像表示 二进制图像 灰度图像 彩色图像 大多数分类算法都要求输入向量&#xff01; rbg的图像矩阵转列向量 大小为 32X32 的话&#xff0c;图像矩阵转列向量是多少维&#xff1f; 32x32x3 3072 维列向量...

车载通信架构 —— 传统车内通信网络FlexRay(较高速度高容错、较灵活拓扑结构)

车载通信架构 —— 传统车内通信网络FlexRay(较高速度高容错、较灵活拓扑结构) 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,…...

如何在Ubuntu的Linux系统中安装MySQL5.7数据库

前往MySQL数据库官网链接地址下载5.7数据库。 MySQL :: Download MySQL Community Server (Archived Versions)使用ssh的可视化工具将下载的mysql-5.7.40-linux-glibc2.12-x86_64.tar.gz文件上传到Linux服务器&#xff0c;并解压文件 tar -zxvf mysql-5.7.40-linux-glibc2.12-x…...

基于Hadoop的区块链海量数据存储的设计与实现

点我完整下载&#xff1a;基于Hadoop的区块链海量数据存储的设计与实现.docx 基于Hadoop的区块链海量数据存储的设计与实现 Design and Implementation of Mass Data Storage for Blockchain based on Hadoop 目录 目录 2 摘要 3 关键词 4 第一章 引言 4 1.1 研究背景 4 1.2 研…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

在rocky linux 9.5上在线安装 docker

前面是指南&#xff0c;后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾&#xff1a; 在上一篇中&#xff0c;我们成功地为应用集成了数据库&#xff0c;并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了&#xff01;但是&#xff0c;如果你仔细审视那些 API&#xff0c;会发现它们还很“粗糙”&#xff1a;有…...

多种风格导航菜单 HTML 实现(附源码)

下面我将为您展示 6 种不同风格的导航菜单实现&#xff0c;每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...

selenium学习实战【Python爬虫】

selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...

React---day11

14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store&#xff1a; 我们在使用异步的时候理应是要使用中间件的&#xff0c;但是configureStore 已经自动集成了 redux-thunk&#xff0c;注意action里面要返回函数 import { configureS…...

蓝桥杯 冶炼金属

原题目链接 &#x1f527; 冶炼金属转换率推测题解 &#x1f4dc; 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V&#xff0c;是一个正整数&#xff0c;表示每 V V V 个普通金属 O O O 可以冶炼出 …...

Fabric V2.5 通用溯源系统——增加图片上传与下载功能

fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill

视觉语言模型&#xff08;Vision-Language Models, VLMs&#xff09;&#xff0c;为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展&#xff0c;机器人仍难以胜任复杂的长时程任务&#xff08;如家具装配&#xff09;&#xff0c;主要受限于人…...