关于placement new 和 placement delete的重载,以及basic_string重载new()实例

关于placement new

在https://blog.csdn.net/qq_42604176/article/details/111997397中已经介绍了placement new的形式。
它的形式为new()/delete().我们将分配好内存的指针送入括号中,就完成了初步的调用了。
其实我们可以定义放任何的东西到()内部。只放一个指针的版本是的new()是标准库先写好给我们的。
我们可以重载operator new,并写出多个版本,如:

Foo* pf = new(300,'c')Foo;	//注意,这里没有传入指针

前提是每一个版本的声明都必须由独特的参数列,其中第一个参数必须是size_t,这是因为当没有()时,进行的是new Foo操作,Foo的大小会被传进operator new中作为第一参数,Foo的大小是个size_t类型。所以我们写的各种各样的版本也必须遵循这个规则。第二第三参数等等可由自己设计。new()括号中的就是第二第三参数,他们可以指定placement arguments 为初值。
下面是实例:

class Foo {
public:Foo() {cout << "Foo::Foo()" << endl; };Foo(int) {cout << "Foo::Foo()" << endl; throw Bad();}	//这里故意抛出异常,用来测试 placement operator delete//【1】一般的operator new()的重载void* operator new(size_t size) {return malloc(size);}//【2】这个是标准库已提供的placement new()的重载形式void* operator new(size_t size, void* start) {return start;}//【3】这个是我们重载的 placement new void* operator new(size_t size, long extra) {return malloc(size + extra);}//【4】这个也是我们重载的 placement newvoid* operator new(size_t size, long extra, char init) {return malloc(size + extra);}//【5】这个也是我们重载的,不过我们故意写错定义参数的类型void* operator new(long extra, char init) {return malloc(extra);}	//很显然这个版本会报错
};

关于placement delete

我们也可以重载placement operator delete,并对应着placement operator new写出多个对应版本,但他们绝对不会被delete调用。
只有当new所调用的ctor抛出异常,才会调用这些重载版本的operator delete。
也就是说重载的placement operator delete是用来释放未能成功创建的对象所占的内存。(正如我们所知,创建一个对象实际上是先申请空间,再调用构造函数。空间申请到了,但是对象却没构造出来,那么理所当然需要将空间释放)
对应上面的四种版本的delete:

//【1】一般的 operator delete()的重载
void operator delete(void*,size_t)
{cout << "operator delete(void*,size_t)" << endl;
}
//【2】对应第二种
void operator delete(void*,void*)
{cout << "operator delete(void*,void*)" << endl;
}
//【3】对应第三种
void operator delete(void*,long)
{cout << "operator delete(void*,long)" << endl;
}
//【4】对应第四种
void operator delete(void*,long,char)
{cout << "operator delete(void*,long,char)" << endl;
}

侯捷老师给出了下面的示例,运行到第五种。我们可以发现,此时的构造函数调用的是第二种构造函数。在之前的定义中,我们在这里抛出了异常。
在这里插入图片描述
接下俩便是这几条语句的执行结果:
在这里插入图片描述
如上所示,这些new都被重载了。所以才会打印信息。
按照道理,在构造函数抛出异常后,会调用自己重载的placement delete,打印信息。但在这里并没有,这是编译器的原因。

关于basic_string重载new()来扩充申请量

basic_string是标准库里面的一个class,就是我们使用的字符串。
如下:

template<...>
class basic_string
{
private:struct Rep {...};...void release() {if(--ref == 0) delete this;}inline static void* operator new(size_t,size_t);inline static void operator delete(void*);inline static Rep* create(size_t);...
};

operator new的具体代码如下:

template<class charT,class traits, class Allocator>
inline void* basic_string<charT,traits,Allocator>::Rep::
operator new(size_t s,size_t extra)
{return Allocator::allocate(s + extra * sizeof(charT));
}

如何使用看这儿:
这里我们把第二参数叫做extra。它的作用是,当使用者去创建一个字符串,如"hello",加上结束符一共6个字符。但是它在分配的时候还会分配extra个字符大小的空间。具体原因不做细究。

template<class charT,class traits,class Allocator>
inline basic_string<charT,traits,Allocator>::Rep*
basic_string<charT,traits,Allocator>::Rep::
create(size_t extra)
{extra = frob_size(extra + 1);Rep *p = new(extra)Rep;...return p;
}

它的placement delete重载之后则长这样:

template<class charT,class traits,class Allocator>
inline void basic_string<charT,traits,Allocator>::Rep::
operator delete(void* ptr)
{Allocator::deallocate(ptr,sizeof(Rep) + reinterpret_cast<Rep*>(ptr)->res * sizeof(charT));
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/377367.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在eclipse中创建web项目(非myeclipse)

在eclipse中创建web项目(非myeclipse) 在eclipse中如何创建dynamic web project项目 本文的演示是从本地文件创建dynamic web project&#xff0c;从svn检出的同时创建dynamic web project于此类似。我们推荐使用解压版的tomcat6.x版本&#xff0c;来作为服务器。可以到http://…

opengl glut 编译

新建工程glut dll工程&#xff0c;本来想创建lib,工程的&#xff0c;但是想起来&#xff0c;gl是状态机机制。dll方便资源共享等。 添加两个include目录 各种手机电脑平台&#xff0c;网络多媒体开发,mmsplayer&#xff0c;QQ514540005 然后将目录下的lib/glut下面所有的.c文件…

bpo是什么意思_BPO的完整形式是什么?

bpo是什么意思BPO&#xff1a;业务流程外包 (BPO: Business Process Outsourcing) BPO is an abbreviation of Business process outsourcing. It is a convention of a company to another company which is an external provider of services or business operations process…

FireFox插件SQLite Manager的使用

最近几天开始高IOS数据库来着&#xff0c;一开始就CoreData的学习&#xff0c;结果高了一天没有一点进展。 没法&#xff0c;还是先老实代码着吧&#xff0c;不过用的火狐插件可视化数据库的操作也是不错的似乎。 网上搜了搜用法&#xff0c;还真没找到有什么的&#xff0c;最后…

针对一个class写出它的内存管理池以及总结出allocator类(三个版本)

目录示例版本1&#xff1a;per-class allocator,1示例版本2&#xff1a;per-class allocator,2最终版本&#xff1a;static allocator针对版本三进行macro如果我们不针对对象做内存管理&#xff0c;那么我们每次进行Foo* p new Foo(x);时总是会调用malloc函数。 尽管malloc函数…

ubuntu 切换用户的命令[shell, linux]

使用ubuntu过程中免不了和shell(终端)打交道, 也不可避免在各种用户之间进行切换, 从而实现对各帐户的管理, 这个就涉及到了一个比较基础又很重要的工作,怎么样切换用户, 对于LINUX老鸟来说,这个根本不值不提的东东却让新手挠头不已, 现在给出普通用户和超级用户切换的命令(附图…

关于new handler与default、delete关键字

在https://blog.csdn.net/qq_42604176/article/details/111638568的operate_new源代码长啥样中谈到过new handler。 当operator new不能够分配出申请的内存时&#xff0c;会抛出bad_alloc 异常。有的编译器会返回0. 当定义成new(nothrow) Foo&#xff1b;就不会抛异常&#xff…

模式匹配运算符–Shell

转载&#xff1a;http://www.firefoxbug.net/?p722 Var/home/firefox/MyProgram/fire.login.name ${Variable#pattern}:如果模式匹配于变量值的开头处&#xff0c;则删除匹配的最短部分&#xff0c;并且返回剩下的部分 例子&#xff1a; [fire]$ echo ${Var#*/} [fire]$ home/…

VC6、BC5、G2.9标准分配器一览

目录VC6标准分配器BC5标准分配器G2.9标准分配器VC6标准分配器 VCx中源码可以在电脑路径中找&#xff1a; [D:\Program Files\VisualStudio\Community\VC\Tools\MSVC\14.28.29333\include\xmemory] 不过太多了。大概在837行左右有关于allocator代码。还是先看侯捷PPT上的吧。 …

css clear属性_CSS中的clear属性

css clear属性CSS | 清除财产 (CSS | clear Property) We know so much about float property and how it is used for styling our web pages. If you do not remember the float property, lets help jog your memory. The float property is used to set the elements in a …

std::alloc具体细节

G2.9 std::alloc的缺点&#xff1a; 1、在alloc::deallocate中没有将拿到的内存资源还给操作系统&#xff0c;在多任务中将占用很大资源 2、alloc::deallocate函数没有检查传入的p指针的有效性。在这里它默认p为alloc::allocate取得。 如果p并非alloc::allocate取得&#xf…

修改函数的返回地址

这篇随笔源自今天看的这篇文章http://www.cnblogs.com/bluesea147/archive/2012/05/19/2508208.html 1. 如何修改函数返回地址 今天主要写测试程序思考和验证了一下这个问题&#xff0c;先看一下这个&#xff23;程序 1 #include <stdio.h>2 void foo(){3 int a,…

从源码角度剖析VC6下的内存分配与切割的运作

目录前言1、heap初始化2、第一次分配内存&#xff0c;计算真正区块大小3、new_region管理中心4、__sbh_alloc_new_group()切割第一次分配好的内存5、开始切割内存前言 malloc与free带来的内存管理是应付小区块的&#xff0c;即SBH(small block heap)&#xff0c;这点也可以从源…

最长公共子序列求序列模板提_最长公共子序列

最长公共子序列求序列模板提Description: 描述&#xff1a; This question has been featured in interview rounds of Amazon, MakeMyTrip, VMWare etc. 这个问题在亚马逊&#xff0c;MakeMyTrip&#xff0c;VMWare等访谈轮次中都有介绍。 Problem statement: 问题陈述&…

求根号m(巴比伦算法)

巴比伦算法是针对求根号m的近似值情况的&#xff0c;它的思想是这样的&#xff1a; 设根号mX0,则如果枚举有答案X(X<X0)&#xff0c;则m/X>X0,当精度要求不高的时候&#xff0c;我们可以看成Xm/XX0,而如果精度要求比较高&#xff0c;我们只需取X和m/X的平均值作为新的枚举…

算法题复习(快排、链表、二分、哈希、双指针)

目录1、快速排序复习2、链表部分复习203. 移除链表元素707. 设计链表206. 反转链表142.环形链表 II3、二分法复习4、哈希法复习5、双指针复习**15. 三数之和****18. 四数之和****27. 移除元素****344. 反转字符串**,简单&#xff0c;双指针从两侧往中间靠拢&#xff0c;并随时s…

码农干货系列【4】--图像识别之矩形区域搜索

简介 定位某个图片的矩形区域是非常有用的&#xff0c;这个可以通过手动的选择某个区域来实现定位&#xff0c;图片相关的软件都提供了这个功能&#xff1b;也可以像本篇一个通过程序来实现智能定位。前者会有误差&#xff0c;效率低下&#xff1b;后者选区精度高&#xff0c;效…

Android中的广播Broadcast详解

今天来看一下Android中的广播机制&#xff0c;我们知道广播Broadcast是Android中的四大组件之一&#xff0c;可见他的重要性了&#xff0c;当然它的用途也很大的&#xff0c;比如一些系统的广播&#xff1a;电量低、开机、锁屏等一些操作都会发送一个广播&#xff0c;具体的And…

.NET线程池

摘要 深度探索 Microsoft .NET提供的线程池&#xff0c; 揭示什么情况下你需要用线程池以及 .NET框架下的线程池是如何实现的&#xff0c;并告诉你如何去使用线程池。 内容 介绍 .NET中的线程池 线程池中执行的函数 使用定时器 同步对象的执行 异步I/O操作 监视线程池 死锁 有关…

《c++特性》

目录多态构造函数和析构函数存在多态吗&#xff1f;虚函数表虚析构函数纯虚函数和抽象类运行时多态和编译时多态的区别继承设计实例指针对象和普通对象的区别正确初始化派生类方式继承和赋值的兼容规则protected 和 private 继承基类与派生类的指针强制转换如何用C实现C的三大特…