重载new和delete

1. 测试代码:

 #include<iostream>
#include<new>
using namespace std;
class A {
public:
A() { cout << "A constructor" << endl; } void* operator new(size_t size)
{
cout << "this is A's new" << endl;
return ::operator new(size);
} void operator delete(void* ptr)
{
cout << "this is A's delete" << endl;
return ::operator delete(ptr);
} ~A() { cout << "A destructor" << endl; }
}; int main()
{
A *a = new A;
delete a;
return ;
}

运行结果:

虽然我们不能改变new/delete的行为,但是通过重载operator new() 和 operator delete()我们可以实现自己想要的内存管理方式,这在内存池的实现中十分关键。关于operator new有几点要注意:

(1)当无法满足所要求分配的空间时,则如果有new_handler,则调用new_handler,否则如果没要求不抛出异常(以nothrow参数表达),则执行bad_alloc异常,否则返回0

(2)重载时,返回类型必须声明为void*

(3)重载时,第一个参数类型必须为表达要求分配空间的大小(字节),类型为size_t

(4)重载时,可以带除(3)以外的其它参数

2.测试代码:

 #include <iostream>
#include <new>
#include <cstdlib>
using namespace std; void* operator new(size_t size)
{
cout << "global Override operator new: " << size << endl;
void * ptr = malloc(size);
return ptr;
} void* operator new(size_t size, int flag)
{
cout << "global Override operator new: " << size << " " << flag << endl;
return (::operator new(size));
} void operator delete (void* ptr)
{
cout << "global Override operator delete" << endl;
free(ptr);
ptr = nullptr;
} void operator delete (void* ptr, int flag)
{
cout << "Override operator delete: " << flag << endl;
::operator delete(ptr);
ptr = nullptr;
}
int main() {
int * ptr = new int();
delete ptr;
cout << endl << "*********************" << endl << endl;
ptr = new() int();
delete ptr;
return ;
}

输出结果:

定位new表达式

1. 测试代码:

 #include <iostream>
using namespace std;
char addr1[];
int main()
{
cout << "******定位new表达式演示***by David***" << endl;
char addr2[];
char *addr3 = new char[];
cout << "addr1 = " << (void*)addr1 << endl;
cout << "addr2 = " << (void*)addr2 << endl;
cout << "addr3 = " << (void*)addr3 << endl;
int *p = nullptr; p = new(addr1)int; ////把内存分配到静态区
*p = ;
cout << (void*)p << " " << *p << endl; p = new(addr2)int; ////把内存分配到栈区
*p = ;
cout << (void*)p << " " << *p << endl; p = new(addr3)int; //把内存分配到堆区
*p = ;
cout << (void*)p << " " << *p << endl;
return ;
}

运行结果:

2.测试代码

 #include <iostream>
#include <string>
#include <new> using namespace std;
const int BUF = ; class JustTesting {
private:
string words;
int number;
public:
JustTesting(const string &s = "Just Testing", int n = )
{
words = s;
number = n;
cout << words << " constructed\n";
} ~JustTesting() { cout << words << " destroyed\n"; }
void Show() const { cout << words << ", " << number << endl; }
}; int main(void)
{
char *buffer = new char[BUF]; // get a block of memory
JustTesting *pc1, *pc2; pc1 = new (buffer)JustTesting; // place object in buffer
pc2 = new JustTesting("heap1", ); // place object on heap cout << "Memory block address:\n" << "buffer: "
<< (void *)buffer << " heap: " << pc2 << endl;
cout << "Memory contents: \n";
cout << pc1 << ": ";
pc1->Show();
cout << pc2 << ": ";
pc2->Show(); JustTesting *pc3, *pc4;
pc3 = new (buffer) JustTesting("bad Idea", );
pc4 = new JustTesting("Heap2", ); cout << "Memory contents: \n";
cout << pc3 << ": ";
pc3->Show();
cout << pc4 << ": ";
pc4->Show(); delete pc2; // free heap1
delete pc4; // free heap2
delete[] buffer; // free buffer
cout << "Done\n"; return ;
}

运行结果:

参考资料

【C++ Primer | 19】控制内存分配的更多相关文章

  1. C++ Primer 笔记——控制内存分配

    1.当我们使用一条new表达式时,实际执行了三步操作. new表达式调用一个名为operator new ( 或者operator new[] ) 的标准库函数.该函数分配一块足够大的,原始的,未命名 ...

  2. [C++] 重载new和delete——控制内存分配

      1.new和delete表达式的工作机理      1)new表达式实际执行了三步 string *sp=new string("aaaa"); ];//string采用默认初 ...

  3. C++之控制内存分配

    一.内存分配方式 在C++中,内存分成5个区,他们分别是堆.栈.自由存储区.全局/静态存储区和常量存储区.栈:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释 ...

  4. c++控制内存分配

    为了满足应用程序对内存分配的特殊需求,C++允许重载new运算符和delete运算符控制内存分配,通过定位new表达式初始化对象(好处是可以在某些场景下避免重新内存分配的消耗) 1.operate n ...

  5. C++ 内存分配操作符new和delete详解

    重载new和delete 首先借用C++ Primer 5e的一个例子: string *sp = new string("a value"); ]; 这其实进行了以下三步操作: ...

  6. 《C++ Primer Plus》读书笔记之十—类和动态内存分配

    第12章 类和动态内存分配 1.不能在类声明中初始化静态成员变量,这是因为声明描述了如何分配内存,但并不分配内存.可以在类声明之外使用单独的语句进行初始化,这是因为静态类成员是单独存储的,而不是对象的 ...

  7. C++ primer plus读书笔记——第12章 类和动态内存分配

    第12章 类和动态内存分配 1. 静态数据成员在类声明中声明,在包含类方法的文件中初始化.初始化时使用作用域运算符来指出静态成员所属的类.但如果静态成员是整形或枚举型const,则可以在类声明中初始化 ...

  8. C++ Primer 学习笔记_98_特殊的工具和技术 --优化内存分配

    特殊的工具和技术 --优化内存分配 引言: C++的内存分配是一种类型化操作:new为特定类型分配内存,并在新分配的内存中构造该类型的一个对象.new表达式自己主动执行合适的构造函数来初始化每一个动态 ...

  9. 【转载】C++内存分配

    原文:C++内存分配 内存泄露相信对C++程序员来说都不陌生.解决内存泄露的方案多种多样,大部分方案以追踪检测为主,这种方法实现起来容易,使用方便,也比较安全. 首先我们要确定这个模块的主要功能: 能 ...

随机推荐

  1. .NET MVC中的ActionResult

    一  摘要 本文介绍了ASP.NET MVC中的ActionResult,本节主要介绍 EmptyResult / Content Result /JavaScriptResult /JsonResu ...

  2. Nginx 学习笔记(二)Web 服务启用 HTTP/2

    个人网站提升为HTTP2.0协议,加速访问 一.条件 1.openssl的版本必须在1.0.2e及以上 2.nginx的版本必须在1.9.5以上 二.编译安装 1.openssl 编译安装 (1)开始 ...

  3. I2C和SPI总线对比

    1 iic总线不是全双工,2根线SCL SDA.spi总线实现全双工,4根线SCK CS MOSI MISO 2 iic总线是多主机总线,通过SDA上的地址信息来锁定从设备.spi总线只有一个主设备, ...

  4. spring注解第06课 @Value

    1.注入<bean>中的属性 支持3种类型的赋值 <bean id="person" class="com.model.Person"> ...

  5. 自动提取文件系统---binwalk(一)

    Binwalk是路由器固件分析的必备工具,该工具最大的优点就是可以自动完成指定文件的扫描,智能发掘潜藏在文件中所有可疑的文件类型及文件系统. 1.Binwalk和libmagic Binwalk的扫描 ...

  6. 滑动条QSlider

    QSlider只提供整数范围 滑块接受Tab键的焦点,并同时提供了一个鼠标滚轮和键盘接口.键盘接口如下: Left/Right 移动水平滑块一个步长.Up/Down 移动垂直滑块一个步长.PageUp ...

  7. 发现一sonar-runner bug

    最近在使用sonar-runner做代码扫描, 在windows环境运行多模块的扫描ok,但是在linux上sonar-runner扫描多模块报错: 先贴sonar-project.propertie ...

  8. luogu P2502 [HAOI2006]旅行

    传送门 边数只有5000,可以考虑\(O(m^2)\)算法,即把所有边按边权升序排序,然后依次枚举每条边\(i\),从这条边开始依次加边,加到起点和终点在一个连通块为止.这个过程可以用并查集维护.那么 ...

  9. luogu P3760 [TJOI2017]异或和

    传送门 对于每个二进制位考虑有多少区间和这一位上为1 从前往后扫每个前缀和,如果当前这个前缀和某一个二进制位上为1,因为区间和由这个前缀和减去前面的前缀和得来,如果减去了这一位为0的前缀和,那么 减去 ...

  10. MySql 安装与使用图文教程

    MySQL是一个关系型数据库管理系统,由瑞典MySQL AB公司开发,目前属于Oracle公司.MySQL是一种关联数据库管理系统,关联数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内, ...