条款8:了解各种不同意义的new和delete

条款 8:了解各种不同意义的 new 和 delete 平时写的 new,其实是new 操作符 的行为是。你能改变的,只有它所调用的那个负责分配内存的 operator new 函数。 阅读详情

new operator,这个操作符是由语言内建的,不能被改变意义,总是做相同的事情。它的动作分为两方面:
第一,它分配足够的内存,用来放置某类型的对象。
第二,它调用一个constructor,为刚才分配的内存中的那个对象设定初值。

你能够改变的是用来容纳对象的那块内存的分配行为。
new operator调用某个函数,执行必要的内存分配动作,你可以重写或重载那个函数,改变其行为。这个函数的名称叫做operator new。

函数operator new通常声明如下:
void * operator new(size_t size);
其返回值类型是void*。此函数返回一个指针,指向一块原始的、未设初值的内存。函数中的size_t参数表示需要分配多少内存,你可以将operator new重载,加上额外的参数,但第一参数的类型必须总是size_t。

你可以像调用任何其他函数一样地调用它:
void *rawMemory=operator new(sizeof(string));
这里的operator new将返回指针,指向一块足够容纳一个string对象的内存。

和malloc一样,operator new的唯一任务就是分配内存。取得operator new返回的内存并将之转换为一个对象,是new operator的责任。当你的编译器看到这样一个句子:

string *ps=new string("Memory Management");

它必须产生一些代码,或多或少会反映以下行为:

void *memory=operator new(sizeof(string));  //取得原始内存(raw memory)用来放置一个string对象
call string::string("Memory Management") on *memory;    //将内存中的对象初始化
string *ps=static_cast<string*>(memory);    //让ps指向新完成的对象

Placement new(特殊版本的operator new)
下面示范如何使用placement new:

class Widget
{
    public:
        Widget(int widgetSize);
        ..
}
Wdiget * constructWidgetInBuffer(void *buffer,int widgetSize)
{
    return new (buffer) Widget(widgetSize);
}

此函数返回指针,指向一个Widget object,它被构造于传递给此函数的一块内存缓冲区上。当程序运行到shared memory或memory-mapped I/O,这类函数可能是有用的,因为在那样的运用中,对象必须置于特定地址,或是置于以特殊函数分配出来的内存上。

对于表达式new (buffer) Widget(widgetSize)
这是new operator的用法之一,其中指定一个额外自变量(buffer)作为new operator“隐式调用operator new”时所用。于是,被调用的operator new除了接受“一定得有的size_t自变量”之外,还接受了一个void*参数,指向一块内存,准备用来接受构造好的对象。这样的operator new就是所谓的placement new,看起来像这样:

void * operator new(size_t, void *location)
{
    return location;
}

看起来很简单,毕竟operator new的目的是要为对象找到一块内存,然后返回一个指针指向它。在placement new的情况下,调用者已经知道指向内存的指针了,因为调用者知道对象应该放在哪里。因此placement new唯一需要做的就是将它获得的指针再返回。至于没有用到(但一定得有)的size_t参数,之所以不赋予名称,为的是避免编译器发出“某物未被使用”的警告。placement new是C++标准程序库的一部分。欲使用placement new,你必须用#include 。

如果你希望将对象产生于heap,请使用new operator。它不但分配内存而且为该对象调用一个constructor。
如果你只是打算分配内存,请调用operator new,那就没有任何constructor会被调用。
如果你打算在heap objects产生时自己决定内存分配方式,请写一个自己的operator new,并使用new operator,它将会自动调用你所写的operator new。
如果你打算在已分配(并拥有指针)的内存中构造对象,请使用placement new。

删除与内存释放
为了避免资源泄漏,每一个动态分配行为都必须匹配一个相应但相反的释放动作。函数operator delete对于内建的delete operator,就好像operator new对于new operator一样。
当你写出这样的代码:

string *ps;
...
delete ps;

它必须既能够析构ps所指对象,又能释放被该对象占用的内存。

内存释放动作是由函数operator delete执行,通常声明如下:

void operator delete(void *memoryToBeDeallocated)

因此,下面这个动作:delete ps;
会造成编译器产生近似这样的代码:

ps->~string();
operator delete(ps);

这里呈现的一个暗示就是,如果你只是打算处理原始的、未设初值的内存,应该完全回避new operator和delete operator,改调用operator new取得内存并以operator delete归还给系统。
这组行为在C++中相当于调用malloc和free。

如果你使用placement new,在某内存块中产生对象,你应该避免对那块内存使用delete operator。因为delete operator会调用operator delete来释放内存,但是该内存内含的对象最初并非是由operator new分配得来的。毕竟placement new只是返回它所接受的指针而已,谁知道那个指针从哪里来呢?所以为了抵消该对象的constructor的影响,你应该直接调用该对象的destructor:

//以下函数用来分配及释放shared memory中的内存
void * mallocShared(size_t size);
void freeShared(void *memory);

void *sharedMemory=mallocShared(sizeof(Widget));
Widget *pw=constructWidgetInBuffer(sharedMemory,10);
...
delete pw;  //无定义!
            //因为sharedMemory来自mallocShared,不是来自operator new
pw->~Widget(); //可以!析构pw所指的Widget对象,
                //但并未释放Widget占用的内存。
freeShared(pw); //可以!释放pw所指的内存,不调用任何destructor

如此例所示,如果交给placement new的原始内存本身是动态分配而得,那么你最终还是得释放那块内存,以免遭受内存泄漏之苦。

数组

string *ps=new string[10];  //分配一个对象数组

由于诞生的是数组,所以new operator的行为与先前产生单一对象的情况略有不同,由一个名为operator new[]的函数负责分配。和operator new一样,operator new[]也可以被重载。

“数组版”与“单一对象版”的new operator的第二个不同是,它所调用的constructor数量。数组版new operator必须针对数组中的每个对象调用一个constructor。

同样道理,当delete operator被用于数组,它会针对数组中的每个元素调用其destructor,然后再调用operator delete[]释放内存。

就好像你可以取代或重载operator delete一样,你也可以取代或重载operator delete[]。不过两者的重载有着相同的限制。

Wireshark教程:解密HTTPS流量 Wireshark教程:如何解密HTTPS流量 阅读详情

相关推荐

Transformer论文解读

Transformer有多牛逼不用多说,时隔7年我们再来看看论文原文,看看这篇深刻改变世界的文章都说了什么。当然逐字逐句解读已经意义不大,我们只列考点。

xian0710830114的专栏 4405

8. 了解各种不同意义的new 和 delete

C++中关于new 的形态主要有三种:new operator, operator new, placement new 三者的用法有着不同,注意区别适用的条件: new operator: new 操作符,和C++语言其它操作符(如+, -, ->, ::....)一样,是由语言内建的,总是完成相同的事情,程序员不能改变其意义。如下为new的一种用法: string *ps = ne

海风林影 1565

滤波器初步入门(非常全面)

主要关注的是-3dB这个点,-3dB就是截止频率所对应的点,我们把功率降至50%以下的信号定义为被衰减掉了(但要跟实际情况相结合,有些信号衰减-3db不够,需要衰减更多)-3dB这个点对应我们的电压来说是0.707。设计电路可以留一定的余量,如果你把4k设计为截止频率,那么4k时候衰减倍数为-3dB通常是不够的,你可以将截止频率设为2k,那么4k的衰减就可以达到15dB(假设),根据自己的需要去设计对应的截止频率。理想的滤波器是当输入的信号频率大于截止频率时,大于部分的频率对应的电压信号直接归0。

yybyybds的博客 5720

《More Effective C++》8:了解各种不同意义的new和delete

《More Effective C++》Rule8:了解各种不同意义的new和delete(上)

杨领well的专栏 2475

Android12 适配 usb 触屏

在 Android 系统中,输入设备 IDC(Input Device Configuration)设备描述文件(.idc)是用于配置和定义输入设备行为和属性的文本文件。 该文件通常在`/system/usr/idc/` 或 `/vendor/usr/idc/`,具体位置因芯片厂商SDK而异。一般情况此类文件是预置到系统,开发者 root 权限才能修改这些文件。输入设备 IDC 设备描述文件在 Android 系统中起到了识别、配置、映射和定制输入设备的作用,使得系统能够准确解析和处理各种输入设备的事件,提

weixin_35723192的博客 1234

在 Linux 64 位上遭遇 Signal 7 与 ST22 SYSTEM_CORE_DUMPED:从 es/implementation=std 到 /dev/shm 的一套落地排查法

摘要: Linux 64位SAP系统出现SYSTEM_CORE_DUMPED和Signal 7(对应SIGBUS)错误时,核心问题是进程因共享内存资源异常被操作系统强制终止。主要诱因包括:1)/dev/shm的tmpfs默认容量不足(通常仅占物理内存50%);2)SAP内存管理参数es/implementation=map在64位场景下的敏感性。解决方案应双管齐下:在实例profile设置es/implementation=std以降低对tmpfs的依赖,同时按(RAM+Swap)*75%重新配置/dev/

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 164

【M8】了解各种不同意义的new和delete

1、首先考虑new operator,new operator 可以认为做了三件事情:a、调用operator new分配一块内存;b、在这块内存上调用构造方法构造对象;返回指针。 2、operator new的声明如下:   void* operator new(size_t size)   和C中的malloc一样,operator new只负责分配内存。 3、考虑,string* p...

weixin_34218890的博客 147

Claude Code Agents 进阶:多代理协作与任务委托

Agent 是一个独立运行的 Claude 实例,它有自己的上下文和任务焦点。│ 主 Claude ││ (协调者) ││ │ │▼ ▼ ▼│ 代码审查 │ │ 测试生成 │ │ 文档编写 ││ │ ││▼汇总结果,完成任务并行处理:多个 Agent 同时工作,提高效率任务隔离:每个 Agent 有独立的上下文专业分工:不同类型的 Agent 擅长不同任务灵活控制:可以指定运行模式、超时等参数。

gaoxiang_120的专栏 336

Nim如何与C/C++/Objc互动

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34190136的博客 1467

Vue3 - Element Plus 全局修改更换主题色配置详细教程,element-plus自定义主题色全局替换主色调强力解决方案,支持动态修改主题颜色/动态皮肤,将默认蓝色主题色更换为其他颜色!

vue3,nuxt3,element-plus,组件库,主题色,修改主题颜色,更换主题色,如何修改组件默认主题蓝色,项目主题色定制,修改失败,主题色覆盖不了,:root直接修改,hover颜色没改,自定义主题色,vue3全局设置elementPlus主题色最新详细修改教程,怎么修改全局的颜色,scss变量,覆盖原来的主题色改为自己的颜色,统一替换,有没有好办法,颜色不变,失败,无效,动态主题切换,主题颜色怎么在项目里直接改,plus主题色更换,覆盖默认主题色,最强最好用,设置主题色,换肤,皮肤,动态更换

🏆 前端领域优质创作者 1万+

基于STM32的蓝牙智能药盒设计

本研究设计了一种基于STM32F103C8T6单片机的蓝牙智能药盒系统,针对老年人用药管理需求,集成了定时提醒、药量检测、环境监测等功能。系统通过LCD1602显示屏实时显示时间与用药信息,支持每日3次定时提醒及3种药物用量设置,采用DHT11温湿度传感器、HX711药量检测模块和红外传感器实现环境监控,并通过蓝牙模块实现远程用药提醒。测试结果表明,系统定时误差≤30秒,温湿度监测精度±2℃,药量检测误差<1g,各项功能运行稳定。该设计为解决老年人用药依从性问题提供了智能化解决方案,具有实用价值和应用前景。

3254968421的博客 543

C++中不同意义的new和delete

using namespace std; class A{ public: A(int a){}; }; int main() { void * rawMemory = operator new [] (10 * sizeof(A)); A * op = static_cast&lt;A*&gt;(rawMemory); for (int i = 0 ; i &l...

jixiansuper的博客 205

一种独特机理驱动的化学反应分类器详解

代码位置第 47-300+ 行// atom_494: 硫原子,度数=2,化合价=2,无H,无电荷!// atom_35: 氧原子,度数=1,1个H,无电荷// atom_347: 氧原子,度数=2,无H,无电荷!→atom_494()[OD1h1+0]→atom_35()→atom_347()特性传统方法(MCS)NameRXN(机理驱动)匹配策略最大公共子结构原子类型模式 + 操作码时间复杂度O(n) - 线性扫描机理理解无内置化学机理原子映射需额外计算自动推导准确性结构相似。

ASKCOS博客 156

More Effective C++(条款8:了解各种不同意义的new和delete)

1. new operator:new操作符,用于动态分配内存并进行初始化;1)调用operator new 获得一块可用内存的地址   2) 调用constructor,为获得的内存中的对象设定初值(初始化对象)new operator是不能被重载的,无论怎样,它总进行这两个步骤。可以被重载的是operator new,即用来获取可用内存的函数,通过重载operator new可以简介优化new...

Unique-You的博客 275

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

条款8:了解不各种不同意义的new和delete 练习

MoreEffectiveC++练习 条款8:了解不各种不同意义的new和delete new operator做两件事:1,调用operator new 分配内存;2, 调用constructor operator new是一个函数: void* operator(size_t size);只分配内存,不调用构造函数。而且operator new返回的是void*型 例子: #

HAN Kai 995

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

深入了解C++中各种不同意义的new和delete

针对new的三种使用方式做了一个使用场景总结,切记操作对应的new 时还需要对应的delete。1、需要将对象创建在堆区,那么就使用也就是new操作符。它会帮你分配内存并调用函数。2、仅需要分配内存,那么就使用,这样就不会调用函数。3、需要在堆区创建对象时自定义内存分配方式,那么就需要重写函数然后使用即可。4、需要在已分配的内存中调用构造函数,那么就使用。...

林夕07 1817

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

More Effective C++ 条款8 了解各种不同意义的new和delete

1. new operator:new操作符,用于动态分配内存并进行初始化; placement new(定位new):new operator的另外一种用法 ,在已分配的内存上构造对象; operator new:标准库的函数,只分配内存不进行初始化(或者传递一个可用的内存地址),可以自己进行重载,也可以主动调用。 注意:new operator是操作符...

ddzai7557的博客 163

条款8:写operator new和operator delete时要遵循常规

如果想控制基于类的数组的内存分配,必须实现operator new的数组形式——operator new[](这个函数常被称为“数组new”,因为想不出"operator new[]")该怎么发音)。但是大多数针对类所写的operator new(包括条款10中的那种)都是只为特定的类设计的,不是为所有的类,也不是为它所有的子类设计的。这意味着,对于一个类x的operator new来说,函数内部的行为在涉及到对象的大小时,都是精确的sizeof(x):不会大也不会小。这看起来也很怪,但简单,合法,有效。

qq_41237850的博客 1085

了解new和delete的合理替换时机——条款50

让我们暂时回到根本原理。首先怎么会有人想要替换编译器提供的operatornew或operatordelete呢?下面是三个最常见的理由: 用来检测运用上的错误。如果将“new所得内存”delete掉却不幸失败,会导致内存泄漏(memoryleaks)。如果在“new所得内存”身上多次delete则会导致不确定行为。如果operatornew持有一串动态分配所得地址,而operatordelete将地址从中移走,倒是很容易检测出上述错误用法。 为了强化效能。编译器所带的oper...

yj_android_develop的博客 316

new()和delete()以及delete,和delete[]的区别

本文均转自互联网,More Effective C++:理解new和delete人们有时好像喜欢故意使C++语言的术语难以理解。比如说new操作符(new operator)和operator new的区别。   当你写这样的代码:string *ps = new string("Memory Management");  你使用的new是new操作符。这个操作符就象siz

jack.A!!en 1040

条款3:尽量用new和delete而不用malloc和free

条款3:尽量用new和delete而不用malloc和free malloc和free(及其变体)会产生问题的原因在于它们太简单:他们不知道构造函数和析构函数。假设用两种方法给一个包含10个string对象的数组分配空间,一个用malloc,另一个用new:   string *stringarray1 =static_cast(malloc(10 * sizeof(str

IT老兵 1258

Effective C++条款50:定制new和delete——了解new和delete的合理替换时机

一、重载operator new和operator delete的理由 我们可以重载编译器的operator new和operator delete,下面给出了三个理由 ①用来检测运用上的错误 下面是一些常见错误: new分配内存,但是没有delete掉,导致内存泄漏 对new所分配的内存,进行多次delete那么会导致不明确的行为 上面这些错误都是可以检测出来的 还有一种错误情况: 一些程序操作数据可能会导致数据“overruns”(写入点在分配内存尾端之后)或“underrun

www_dong的博客 262

带你读懂Effective C++(八,九): 定制new和delete, 杂项讨论

摘要:本文系统讲解了C++内存管理的关键技术,包括new-handler行为准则、new/delete的合理替换时机、placement new/delete的配对规则等核心内容。重点阐述了自定义内存管理组件的规范要求:new-handler需遵循释放内存、更换handler等5个行为准则;替换new/delete需满足调试、性能优化等5种场景;placement delete必须与new严格配对以避免内存泄漏。同时强调了编译器警告的重要性及标准库/Boost的使用价值。

2403_87381789的博客 1198

More Effective C++:不同new和delete

人们有时似乎喜欢故意使C++语言的术语难以理解。比如说new操作符(new operator)和operator new的区别。 当你写这样的代码: string *ps = new string("Memory Management"); 你使用的new是new操作符。这个操作符就象sizeof一样是语言内置的,你不能改变它的含义,它的功能总是一样的。它要完成的功能分成两部分。第一部分是分配足够的内存以便容纳所需类型的对象。第二部分是它调用构造函数初始化内存中的对象。new操作符总

Hashmat的专栏 954

C++中new和delete运算符详解

本文内容摘自More Effective C++(Scott Meyers 著)一书,详细解释了new和delete操作符的用法。 一、new 操作符(new operator) 人们有时好像喜欢有意使C++语言的术语难以理解。比方说new操作符(new operator)和operator new的差别。 当你写这种代码: string *ps = new string("Me...

魔筝炼药师 2428

条款5:对应的new和delete要采用相同的形式

用delete的时候,也有两件事发生:首先,为将被释放的内存调用一个或多个析构函数,然后,释放内存(通过operator delete 函数,详见条款8和m8)。至少,stringarray指向的100个string对象中的99个不会被正确地摧毁,因为他们的析构函数永远不会被调用。这个规则对喜欢用typedef的人来说也很重要,因为写typedef的程序员必须告诉别人,用new创建了一个typedef定义的类型的对象后,该用什么形式的delete来删除。//一个人的地址,共4行,每行一个string。

qq_41237850的博客 627
上一篇: 数据结构--邻接多重表下的无向图的生成树
下一篇: Lesson 1: 游戏程序的组成
Nim的辙迹
博客等级 码龄10年 17粉丝 40原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值