人们有时似乎喜欢故意使C++语言的术语难以理解。比如说new操作符(new operator)和operator new的区别。
当你写这样的代码:
string *ps = new string("Memory Management");
你使用的new是new操作符。这个操作符就象sizeof一样是语言内置的,你不能改变它的含义,它的功能总是一样的。它要完成的功能分成两部分。第一部分是分配足够的内存以便容纳所需类型的对象。第二部分是它调用构造函数初始化内存中的对象。new操作符总是做这两件事情,你不能以任何方式改变它的行为。
你所能改变的是如何为对象分配内存。new操作符调用一个函数来完成必需的内存分配,你能够重写或重载这个函数来改变它的行为。new操作符为分配内存所调用函数的名字是operator new。
函数operator new 通常这样声明:
void * operator new(size_t size);
返回值类型是void*,因为这个函数返回一个未经处理(raw)的指针,未初始化的内存。(假如你喜欢,你能写一种operator new函数,在返回一个指针之前能够初始化内存以存储一些数值,但是一般不这么做。)参数size_t确定分配多少内存。你能增加额外的参数重载函数operator new,但是第一个参数类型必须是size_t。(有关operator new更多的信息参见Effective C++ 条款8至条款10。)
你一般不会直接调用operator new,但是一旦这么做,你可以象调用其它函数一样调用它:
void *rawMemory = operator new(sizeof(string));
操作符operator new将返回一个指针,指向一块足够容纳一个string类型对象的内存。
就象malloc一样,operator new的职责只是分配内存。它对构造函数一无所知。operator new所了解的是内存分配。把operator new 返回的未经处理的指针传递给一个对象是new操作符的工作。当你的编译器遇见这样的语句:
string *ps = new string("Memory Management");
它生成的代码或多或少与下面的代码相似(更多的细节见Effective C++条款8和条款10,还有我的文章Counting object里的注释。):
void *memory = // 得到未经处理的内存
operator new(sizeof(string)); // 为String对象
call string::string("Memory Management") //初始化
on *memory; // 内存中
// 的对象
string *ps = // 是ps指针指向
static_cast(memory); // 新的对象
注重第二步包含了构造函数的调用,你做为一个程序员被禁止这样去做。你的编译器则没有这个约束,它可以做它想做的一切。因此假如你想建立一个堆对象就必须用new操作符,不能直接调用构造函数来初始化对象。
Placement new
有时你确实想直接调用构造函数。在一个已存在的对象上调用构造函数是没有意义的,因为构造函数用来初始化对象,而一个对象仅仅能在给它初值时被初始化一次。但是有时你有一些已经被分配但是尚未处理的的(raw)内存,你需要在这些内存中构造一个对象。你可以使用一个非凡的operator new ,它被称为placement new。
下面的例子是placement new如何使用,考虑一下:
class Widget {
public:
Widget(int widgetSize);
...
};
Widget * constrUCtWidgetInBuffer(void *buffer,
int widgetSize)
{
return new (buffer) Widget(widgetSize);
}
这个函数返回一个指针,指向一个Widget对象,对象在转递给函数的buffer里分配。当程序使用共享内存或memory-mapped I/O时这个函数可能有用,因为在这样程序里对象必须被放置在一个确定地址上或一块被例程分配的内存里。(参见条款4,一个如何使用placement new的一个不同例子。)
在constructWidgetInBuffer里面,返回的表达式是:
new (buffer) Widget(widgetSize)
这初看上去有些生疏,但是它是new操作符的一个用法,需要使用一个额外的变量(buffer),当new操作符隐含调用operator new函数时,把这个变量传递给它。被调用的operator new函数除了待有强制的参数size_t外,还必须接受void*指针参数,指向构造对象占用的内存空间。这个operator new就是placement new,它看上去象这样:
void * operator new(size_t, void *location)
{
return location;
}
这可能比你期望的要简单,但是这就是placement new需要做的事情。究竟operator new的目的是为对象分配内存然后返回指向该内存的指针。在使用placement new的情况下,调用者已经获得了指向内存的指针,因为调用者知道对象应该放在哪里。placement new必须做的就是返回转递给它的指针。(没有用的(但是强制的)参数size_t没有名字,以防止编译器发出警告说它没有被使用;见条款6。) placement new是标准C++库的一部分。为了使用placement new,你必须使用语句#include (或者假如你的编译器还不支持这新风格的头文件名)。
让我们从placement new回来片刻,看看new操作符(new operator)与operator new的关系,你想在堆上建立一个对象,应该用new操作符。它既分配内存又为对象调用构造函数。假如你仅仅想分配内存,就应该调用operator new函数;它不会调用构造函数。假如你想定制自己的在堆对象被建立时的内存分配过程,你应该写你自己的operator new函数,然后使用new操作符,new操作符会调用你定制的operator new。假如你想在一块已经获得指针的内存里建立一个对象,应该用placement new。
Deletion and Memory Deallocation
为了避免内存泄漏,每个动态内存分配必须与一个等同相反的deallocation对应。函数operator delete与delete操作符的关系与operator new与new操作符的关系一样。当你看到这些代码:
string *ps;
...
delete ps; // 使用delete 操作符
你的编译器会生成代码来析构对象并释放对象占有的内存。
Operator delete用来释放内存,它被这样声明:
void operator delete(void *memoryToBeDeallocated);
因此, delete ps;
导致编译器生成类似于这样的代码:
ps->~string(); // call the object's dtor
operator delete(ps); // deallocate the memory
// the object occupied
这有一个隐含的意思是假如你只想处理未被初始化的内存,你应该绕过new和delete操作符,而调用operator new 获得内存和operator delete释放内存给系统:
void *buffer = // 分配足够的
operator new(50*sizeof(char)); // 内存以容纳50个char
//没有调用构造函数
...
operator delete(buffer); // 释放内存
// 没有调用析构函数
这与在C中调用malloc和free等同。
假如你用placement new在内存中建立对象,你应该避免在该内存中用delete操作符。因为delete操作符调用operator delete来释放内存,但是包含对象的内存最初不是被operator new分配的,placement new只是返回转递给它的指针。谁知道这个指针来自何方?而你应该显式调用对象的析构函数来解除构造函数的影响:
// 在共享内存中分配和释放内存的函数 void * mallocShared(size_t size);
void freeShared(void *memory);
void *sharedMemory = mallocShared(sizeof(Widget));
Widget *pw = // 如上所示,
constructWidgetInBuffer(sharedMemory, 10); // 使用
// placement new
...
delete pw; // 结果不确定! 共享内存来自
// mallocShared, 而不是operator new
pw->~Widget(); // 正确。 析构 pw指向的Widget,
// 但是没有释放
//包含Widget的内存
freeShared(pw); // 正确。 释放pw指向的共享内存
// 但是没有调用析构函数
如上例所示,假如传递给placement new的raw内存是自己动态分配的(通过一些不常用的方法),假如你希望避免内存泄漏,你必须释放它。(参见我的文章Counting objects里面关于placement delete的注释。)
Arrays
到目前为止一切顺利,但是还得接着走。到目前为止我们所测试的都是一次建立一个对象。怎样分配数组?会发生什么?
string *ps = new string[10]; // allocate an array of
// objects
被使用的new仍然是new操作符,但是建立数组时new操作符的行为与单个对象建立有少许不同。第一是内存不再用operator new分配,代替以等同的数组分配函数,叫做operator new[](经常被称为array new)。它与operator new一样能被重载。这就答应你控制数组的内存分配,就象你能控制单个对象内存分配一样(但是有一些限制性说明,参见Effective C++ 条款8)。
(operator new[]对于C++来说是一个比较新的东西,所以你的编译器可能不支持它。假如它不支持,无论在数组中的对象类型是什么,全局operator new将被用来给每个数组分配内存。在这样的编译器下定制数组内存分配是困难的,因为它需要重写全局operator new。这可不是一个能轻易接受的任务。缺省情况下,全局operator new处理程序中所有的动态内存分配,所以它行为的任何改变都将有深入和普遍的影响。而且全局operator new有一个正常的签名(normal signature)(也就单一的参数size_t,参见Effective C++条款9),所以假如你 决定用自己的方法声明它,你马上使你的程序与其它库不兼容基于这些考虑,在缺乏operator new[]支持的编译器里为数组定制内存治理不是一个合理的设计。)
第二个不同是new操作符调用构造函数的数量。对于数组,在数组里的每一个对象的构造函数都必须被调用:
string *ps = // 调用operator new[]为10个
new string[10]; // string对象分配内存,
// 然后对每个数组元素调用
// string对象的缺省构造函数。
同样当delete操作符用于数组时,它为每个数组元素调用析构函数,然后调用operator delete来释放内存。
就象你能替换或重载operator delete一样,你也替换或重载operator delete[]。在它们重载的方法上有一些限制。请参考优秀的C++教材。
new和delete操作符是内置的,其行为不受你的控制,凡是它们调用的内存分配和释放函数则可以控制。当你想定制new和delete操作符的行为时,请记住你不能真的做到这一点。你只能改变它们为完成它们的功能所采取的方法,而它们所完成的功能则被语言固定下来,不能改变。(You can modify how they do what they do, but what they do is fixed by the language)
相关推荐
医药行业SAP序列号管理深度解析:如何满足GMP合规要求
本文深度解析了医药行业如何利用SAP序列号管理构建满足GMP合规要求的数字化追溯体系。文章详细阐述了SAP序列号在实现从生产到患者全流程“一物一码”精准追溯中的核心作用,并探讨了其与质量管理、冷链监控等系统的关键集成配置,为医药企业应对严格监管、保障产品质量与安全提供了切实可行的技术方案。
6278 - is allocated with array new [], but deleted with scalar delete
6278 - is allocated with array new [], but deleted with scalar deleteConsequenceDestructors will not be calledThe calling function is allocating memory with operator
学习笔记【Day 20】鸿蒙PC应用在SD WAN MSTP场景用CodeArts test工具测试过程
多生成树协议(MSTP)作为二层网络高可靠、无环路的核心技术,其在鸿蒙 PC 上的兼容性与稳定性测试尤为重要。本文结合华为云 CodeArts TestPlan 全流程测试管理平台,详细拆解鸿蒙 PC 端 MSTP 功能的测试设计、环境搭建、执行验证。1.测试左移,保障迭代效率CodeArts TestPlan 将 MSTP 测试从后期集成阶段 “左移” 至开发早期,通过可复用用例库与自动化脚本,支持每次代码提交后的快速回归测试,避免网络功能稳定性因迭代被破坏。2.平台化工具破解复杂场景测试难题。
C++中new和delete运算符详解
本文内容摘自More Effective C++(Scott Meyers 著)一书,详细解释了new和delete操作符的用法。 一、new 操作符(new operator) 人们有时好像喜欢有意使C++语言的术语难以理解。比方说new操作符(new operator)和operator new的差别。 当你写这种代码: string *ps = new string("Me...
OCSP环境搭建--Windows Server 2016
OCSP环境搭建--Windows Server 2016 一. OCSP环境中相关信息 1. 服务器1 操作系统:Win Server 2016 Standard版 IP地址:172.16.0.19/23,网关:172.16.0.1,首选DNS:127.0.0.1 服务器角色:域控制器、证书颁发机构、radius服务器、DNS服务器 ...
蓝桥杯历年真题分类汇总(史上最全版本,一定不要错过)
天再高又怎样,踮起脚尖就更接近阳光。 满满的 题型总结 历年真题 视频讲解 比赛技巧 题型总结 2021 2020 2019 2018 2017 2016 2015 2014 2013 ...
New和Delete
人们有时似乎喜欢故意使C++语言的术语难以理解。比如说new操作符(new operator)和operator new的区别。 当你写这样的代码: string *ps = new string("Memory Management"); 你使用的new是new操作符。这个操作符就象sizeof一样是语言内置的,你不能改变它的含义,它的功能总是一样的。它要完成的功能分成两部分。第一部分是分配足够的内存以便容纳所需类型的对象。第二部分是它调用构造函数初始化内存中的对象。n
MySQL 分库分表及其平滑扩容方案
MyCAT不仅仅可以用作读写分离,以及分表分库、容灾管理,而且可以用于多租户应用开发、云平台基础设施,让你的架构具备很强的适应性和灵活性。分表对于一张多行(记录)多列(字段)的二维数据表,又分两种情形(1)垂直分表竖向切分,不同分表存储不同的字段,可以把不常用或者大容量、或者不同业务的字段拆分出去;扩容前每个节点的数据,有一半要迁移至一个新增节点中,对应关系比较简单。此时,四个节点的数据都已完整,只是有冗余(多存了和自己配对的节点的那部分数据),择机清除即可(过后随时进行,不影响业务)。...
《More Effective C++》8:了解各种不同意义的new和delete
《More Effective C++》Rule8:了解各种不同意义的new和delete(上)
基于C#的ASP.NET开发的党史学习网站课设
开展党史学习教育,就是要以史为镜、以史明志,把苦难辉煌的过去、日新月异的现在、光明宏大的未来贯通起来,在鉴往知来中砥砺前行,在乱云飞渡中把准航向,在凝心聚力中团结奋斗,共同创造新的历史伟业。登陆按钮与数据库进行连接,逻辑实现是如图3.1.3所示,自己定义一个SQL查询语句,将账号、密码放入SQL查询语句中,用sqlDataReader.HasRows语句进行逐一比较,找出结果,将用户名存入session并调用cookies,如果结果存在就关闭数据库,进行数据跳转,并弹出登陆成功的提示框,并关闭数据库。
解锁VS2022!手把手教你本地部署Deepseek
在 VS2022 中本地部署 Deepseek,我们首先需要确保硬件资源的充足,如高性能的 GPU、大容量内存和高速存储等,这是模型稳定运行的基石。如果生成的摘要能够准确概括原文的核心内容,就表明 Deepseek 模型在文本分析方面的功能正常,部署稳定可靠。这对于开发者来说,能够大大提高开发效率,当遇到一些常见的功能实现时,可以借助 Deepseek 模型快速生成基础代码框架,减少手动编写的工作量。在大语言模型的蓬勃发展的当下,Deepseek 凭借其卓越的性能和创新的技术,已然成为该领域的佼佼者。
More Effective C++ 条款08:理解各种不同意义的new和delete
More_Effective_C++08
从零搭建 SAP ALE/IDoc:自定义 IDoc 结构、Outbound 发送、Inbound 入库与排错全流程
本文介绍了SAP系统中ALE和IDoc技术的应用,用于解决分布式系统集成中的数据传递问题。主要内容包括: ALE/IDoc技术概述 ALE通过消息驱动方式实现业务数据传递 IDoc作为标准化数据信封,包含控制信息、业务数据和状态记录 支持SAP与非SAP系统间集成 核心概念 ALE的价值在于业务消息传递而非远程调用 IDoc由控制记录、数据记录和状态记录三部分组成 WE60工具用于查看IDoc文档结构 实践案例 演示如何将自定义业务表数据打包为IDoc 详细说明IDoc结构定义步骤(段、基本类型、消息类型)
《More Effective C++》08. 了解各种不同意义的new和delete
1. new operator:new操作符,用于动态分配内存并进行初始化; 1)调用operator new 获得一块可用内存的地址 2) 调用constructor,为获得的内存中的对象设定初值(初始化对象) new operator是不能被重载的,无论怎样,它总进行这两个步骤。可以被重载的是operator new,即用来获取可用内存的函数,通过重载operator new可以简介优化new operator。 string *ps = new string("hello worl...
ssm框架搭建
这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载
怀旧版电脑GBC模拟器
再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。
More Effective C++ 条款8 了解各种不同意义的new和delete
1. new operator:new操作符,用于动态分配内存并进行初始化; placement new(定位new):new operator的另外一种用法 ,在已分配的内存上构造对象; operator new:标准库的函数,只分配内存不进行初始化(或者传递一个可用的内存地址),可以自己进行重载,也可以主动调用。 注意:new operator是操作符...
OV9734 DATASHEET,完整规格书
OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等
More Effective C++ 08:理解各种不同含义的 new 和 delete
string *ps = new string("Memory Management"); 当你写这样的代码,你使用的new是new操作符。 这个操作符就像sizeof一样是语言内置的,你不能改变它的含义,它的功能总是一样的。它要完成的功能分成两部分。第一部分是分配足够的内存以便容纳所需类型的对象。第二部分是它调用构造函数初始化内存中的对象. 你所能改变的是如何为对象分配内存。new 操作符调用一个函数来完成必需的内存分配,你能够重写或重载这个函数来改变它的行为。new操作符为分配内存所调用函数的名字是o
jre9下载 jdk9
(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】
More Effective C++ 条款08:了解各种不同意义的new和delete
当你写string *ps = new string(“Hands up!”)时,你所使用的new是所谓的new operator,它其实干了两件事: 一、分配足够的内存(实际大小是大于所创建的对象大小) 二、调用对象构造函数,为刚才分配的内存对象设定初值。 new operator永远干这两件事,无论如何你不能改变其行为。 上面的那段代码大约反映以下的行为: void *mem = operator new(sizeof(string)); call string::string(“Hands
More Effective C++之 Item M8:理解各种不同含义的new和delete
人们有时好像喜欢故意使C++语言的术语难以理解。比如说new操作符(new operator)和new操作(operator new)的区别。 当你写这样的代码: string *ps = new string("Memory Management"); 你使用的new是new操作符。这个操作符就象sizeof一样是语言内置的,你不能改变它的含义,它的功能总是一样的。它要完成的功能...
More Effective C++ ——08_理解各种不同含义的new和delete
条款八:理解各种不同含义的new和delete1.区别 new操作符(new operator)和operator new string *ps = new string("Memory Management");这里的new是new operator。就象sizeof一样是语言内置的,你不能改变它的含义,它完成两个功能。 1)分配内存 2)调用构造函数初始化内存中的对象。(C语言中ma
C++之理解不同含义的new和delete(6)---《More Effective C++》
C++语言中很多问题都是非常细小的,例如new操作符(new operator)和new 操作(operator new)的区别:注意: 我们生成的placement delete版本什么时候使用呢?注意一下哈!只要在placement new抛出异常时候,编译器才会调用placement delete版本,这个时候因为构造失败,所以需要释放内存。其他情况下如果我们想要使用placement de
More Effective C++之Item M8:理解各种不同含义的new和delete
人们有时好像喜欢故意使C++语言的术语难以理解。比如说new操作符(new operator)和new操作(operator new)的区别。 当你写这样的代码: string *ps = new string("Memory Management"); 你使用的new是new操作符。这个操作符就象sizeof一样是语言内置的,你不能改变它的含义,它的功能总是一样的。它要完成的功能分成两部分
More Effective C++----(8)理解各种不同含义的new和delete
Item M8:理解各种不同含义的new和delete
more effective c++笔记2-----Item M8:理 解各种不同含义的new和delete
一.说在前面的话 1.new operator:new 是一个操作符 2.operator new:new 操作符在进行内存分配时所调用的函数,通过这个函数来最终完成内存的分配,函数operator new 通常这样声明:void * operator new(size_t size),注意返回的是一个void*类型,但这个函数与普通函数又有些区别,他是一个重载操作符函数,类似于 bool
编程交流与学习--More Effective C++的学习-Item M8:理解各种不同含义的new和delete
new操作符(new operator)和new操作(operator new)的区别。 string *ps = new string("Memory Management");使用的new是new操作符。这个操作符就象sizeof一样是语言内置的,你不能改变它的含义,它的功能总是一样的。它要完成的功能分成两部分。第一部分是分配足够的内存以便容纳所需类型的对象。第二部分是它调用构造函数
More Effective C++(条款8:了解各种不同意义的new和delete)
1. new operator:new操作符,用于动态分配内存并进行初始化;1)调用operator new 获得一块可用内存的地址 2) 调用constructor,为获得的内存中的对象设定初值(初始化对象)new operator是不能被重载的,无论怎样,它总进行这两个步骤。可以被重载的是operator new,即用来获取可用内存的函数,通过重载operator new可以简介优化new...
8.了解各种不同意义的new和delete
new operator和 operator new的区别 通常我们使用的new是new operator。不能改变其意义。new operator做两件事。1、分配足够放置对象的内存。2、调用一个constructor,为刚才分配的内存中那个对象设定初值。 operator new的声明如下: void *operator new(size_t size); 我们可以重载这个ne
655



被折叠的 条评论
为什么被折叠?



