C++中的new、operator new与placement new
new operator
new operator是我们常用的new。
new 和 delete 是用来在 堆上申请和释放空间的 ,是 C++ 定义的 关键字,和 sizeof 一样。
实际 new / delete 和 malloc / free 最大的区别是,前者对于 自定义类型 除了可以开辟空间,还会调用构造和析构函数
-
分配内存,如果类A重载了operator new,那么将调用A::operator new(size_t )来完成,如果没有重载,就调用::operator new(size_t ),即全局new操作符来完成
-
调用构造函数生成类对象;
-
返回相应指针

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 是用来在 堆上申请和释放空间的 ,是 C 定义的 关键字,和 sizeof 一样。 实际 new / delete 和 malloc / free 最大的区别是,前者对于 自定义类型 除了可以开辟空间,…...
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"执行结果输出如下: curl -X GET "https://localhost:9200/_cat/ml/ano…...
Luminar Neo1.16.0(ai智能图像处理)
Luminar Neo是一款ai智能图像编辑软件,它专注于使用人工智能技术来实现对照片的快速、高效和创造性的编辑。 具体来说,Luminar Neo可以自动移除景观或旅行照片中令人分心的元素,例如电话线、电线杆等,从而增强照片的整体质量。同…...
ElasticSearch之cat aliases API
执行aliases命令,如下: curl -X GET "https://localhost:9200/_cat/aliases?pretty&vtrue" --cacert $ES_HOME/config/certs/http_ca.crt -u "elastic:ohCxPHQBEs5*lo7F9"执行结果输出如下: alias index …...
bash编程 数组和for循环的应用
bash编程 数组和for循环的应用 1、问题背景2、bash 定义数组3、for循环遍历输出数组所有元素4、编写bash脚本输出每个端口是否在监听状态 1、问题背景 linux服务器开机后,需要检查一组端口是否在监听,以便判断这些端口对应的服务是否在运行。可以考虑使…...
Python基础:标准库概览
1. 标准库介绍 Python 标准库非常庞大,所提供的组件涉及范围十分广泛,正如以下内容目录所显示的。这个库包含了多个内置模块 (以 C 编写),Python 程序员必须依靠它们来实现系统级功能,例如文件 I/O,此外还有大量以 Pyt…...
C#,《小白学程序》第三课:类class,类的数组及类数组的排序
类class把数值与功能巧妙的进行了结合,是编程技术的主要进步。 下面的程序你可以确立 分数 与 姓名 之间关系,并排序。 1 文本格式 /// <summary> /// 同学信息类 /// </summary> public class Classmate { /// <summary> /…...
建筑结构健康监测系统和传统人工监测的区别
在繁华的城市里,建筑结构作为城市生命线的重要一环,其安全与稳定对城市的运转和居民的生活至关重要。为了更好地守护建筑结构的健康,WITBEE万宾自主研发建筑结构健康监测系统让建筑安全,在上一个台阶。 WITBEE万宾建筑结构健康监测…...
二 使用GPIO的复用功能 利用USART 实现printf()
参考这篇: STM32串口通信详解 1. 关于USART USART ( universal synchronous / asynchronous receiver /transmitter) 是一种串行通讯协议 , 允许设备通过串行端口进行数据传输, USART 能够以同步或者异步的方式进行工作,在实际的运用中&…...
C#中的警告CS0120、CS0176、CS0183、CS0618、CS0649、CS8600、CS8601、CS8602、CS8604、CS8625及处理
目录 一、CS0120 二、CS0176 1.解决前 2.解决后 3.解决办法 三、CS0183 四、CS0618 五、CS8600 六、CS8602 七、CS8622 1. 解决前: 2. 解决后: 3.解决方法: 八、CS8604和CS8625 九、CS0649 十、CS8601 一、CS0120 严重性 代…...
js中声明变量的关键字(const,let,var)
const 特点: const不允许在同一作用域重复声明,块级作用域暂时性死区,在声明之前,该变量是不可用的const声明的是一个只读变量,声明之后不能改变其值,一旦声明必须初始化但是const定义的对象属性是可以修…...
Android13 launcher循环切页
launcher 常规切页:https://blog.csdn.net/a396604593/article/details/125305234 循环切页 我们知道,launcher切页是在packages\apps\Launcher3\src\com\android\launcher3\PagedView.java的onTouchEvent中实现的。 1、滑动限制 public boolean onT…...
Java学习路线第一篇:Java基础(2)
这篇则分享Java学习路线第一part:Java基础(2) 从看到这篇内容开始,你就是被选定的天命骚年,将承担起学完Java基础的使命,本使命为单向契约,你可选择YES或者选择YES。 具体路线安排:…...
网络工程师精华篇,50种网络故障及解决方法大集合
上午好,我的网工朋友。 做网络工程师,自然离不开网络,而日常工作中能搞多少大项目?最常见的其实还是网络故障的处理了。 怎么最高效地排查网络故障?怎么简单几招通网? 今天就从基础的入手,分…...
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灰狼算法优化卷积长短…...
线性分类器--图像表示
整个模型 图像表示 二进制图像 灰度图像 彩色图像 大多数分类算法都要求输入向量! rbg的图像矩阵转列向量 大小为 32X32 的话,图像矩阵转列向量是多少维? 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服务器,并解压文件 tar -zxvf mysql-5.7.40-linux-glibc2.12-x…...
基于Hadoop的区块链海量数据存储的设计与实现
点我完整下载:基于Hadoop的区块链海量数据存储的设计与实现.docx 基于Hadoop的区块链海量数据存储的设计与实现 Design and Implementation of Mass Data Storage for Blockchain based on Hadoop 目录 目录 2 摘要 3 关键词 4 第一章 引言 4 1.1 研究背景 4 1.2 研…...
label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...
C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...
Java毕业设计:WML信息查询与后端信息发布系统开发
JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发,实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构,服务器端使用Java Servlet处理请求,数据库采用MySQL存储信息࿰…...
Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...
Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换
目录 关键点 技术实现1 技术实现2 摘要: 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式(自动驾驶、人工驾驶、远程驾驶、主动安全),并通过实时消息推送更新车…...
go 里面的指针
指针 在 Go 中,指针(pointer)是一个变量的内存地址,就像 C 语言那样: a : 10 p : &a // p 是一个指向 a 的指针 fmt.Println(*p) // 输出 10,通过指针解引用• &a 表示获取变量 a 的地址 p 表示…...
WEB3全栈开发——面试专业技能点P4数据库
一、mysql2 原生驱动及其连接机制 概念介绍 mysql2 是 Node.js 环境中广泛使用的 MySQL 客户端库,基于 mysql 库改进而来,具有更好的性能、Promise 支持、流式查询、二进制数据处理能力等。 主要特点: 支持 Promise / async-await…...
Qt的学习(二)
1. 创建Hello Word 两种方式,实现helloworld: 1.通过图形化的方式,在界面上创建出一个控件,显示helloworld 2.通过纯代码的方式,通过编写代码,在界面上创建控件, 显示hello world; …...
