c++primer 第十九章笔记 01 控制内存分配

19.1控制内存分配

比如你做一款应用程序,它对内存有特殊的需求,编译器自带的标准内存管理机制无法直接应用于这些程序
它需要我们自定义分配的细节,
我们要做的事情就是将关键字new将对象放置在特定的内存空间中,
我们要重载new运算符和delete运算符以控制内存分配

19.1.1重载new和delete

//new表达式
string *sp =new string("a value");  //分配并初始化一个string对象
string *arr =new string[10];       //分配10个默认初始化的string对象

new表达式实际执行了三个步骤
(1)new表达式调用了一个名为operator new的标准库函数。该函数分配一块足够大的,原始的,未命名的内存空间一变存储特定类型的对象(或者对象的数组);
(2)编译器运行时相应的构造函数以构造这些对象,并为其传入初始值
(3)对象被分配了空间并构造完成,返回一个指向该对象的指针

//用delete 表达式删除一个动态分配的对象
delete sp; //销毁*sp,然后释放sp指向的内存空间
delete []arr;//销毁数组中的元素,然后释放对应的内存空间

delete表达式执行了两个步骤
(1)对sp所指的对象或者arr所指的数组中的元素执行对应的析构函数
(2)编译器调用名为operater delete的标准库函数施法内存空间

下面是我们自己定义operator new函数和operator delete,来达到控制内存分配的目的
注意:当自定义了operator new函数和operator delete函数,必须保证函数是正确的,因为我们担负起了
控制动态内存分配的职责。他们是程序整个处理过程中至关重要的一部分

operatornew 接口和operator delete接口
先看标准库给的operator new函数 和 operator delete函数的八个重载版本,前面四个版本可能抛出bad_alloc异常
后面四个不会

//这些版本可能抛出异常
void *operator new (size_t); //分配一个对象
void *operator new[](size_t);//分配一个数组
void *operator delete(void *)noexcept; //释放一个对象
void *operator delete[](void *)noexcept;//释放一个数组

//这些版本承诺不会抛出异常
void *operator new (size_t,nothow_t&)noexcept;
void *operator new[](size_t,nothow_t&)noexcept;
void *operator delete(void *,nothow_t&)noexcept;
void *operator delete[](void *,nothow_t&)noexcept;


struct MyClass{
MyClass(){cout<<"MyClass conststructde\n";}
~MyClass(){cout<<"MyClass destroyed\n";}
};

int main()
{
//可以通过判断pt是否为空,判断是否有异常
MyClass *pt =new (std::nothrow)MyClass; //nothrow 调用不会抛出异常的版本
delete pt;//调用析构函数
}

operator new函数 和 operator delete函数,可以定义为全局作用域,也可以定义为成员函数(默认static)

术语:new表达式与operator new函数
跟其他的operator函数不同(operator<<==!=等等),这两个函数并没有重载new表达式或delete表达式。
实际上,我们根本无法自定义new表达式或delete表达式的行为

一条new表达式的执行过程总是先调用 operator new函数以获取内存空间,然后在得到的内存空间中构造对象,
一天delete表达式的执行过程总是先销毁对象,然后调用operator delete 函数施法对象所占的空间。这一过程
不会改变对象的内容或者操作

自定义operator new函数 和operator delete 函数的目的在于改变内存分配的方式
不会改变new运算符和delete运算符的基本含义

malloc函数与free函数
csdlib头文件
malloc函数():接受一个表示带分配字节数的size_t,返回指向分配空间的指针或者返回0以表达分配失败
free函数:接受一个void*,它是malloc返回的指针的副本,free将相关内存返回给系统,调用free(0)没有任何意义

编写operator new 和 operator delete的一种简单方式

void  *operator new (size_t size)
{
       if(void *mem =malloc(size))
     {
       return mem;
     }
       else 
     {
       throw bad_alloc();
     }
}

void operator delete(void *mem)noexcept
{
free(mem);
}

19.1.1节练习
练习19.1

void  *operator new (size_t size)
{
       if(void *mem =malloc(size))
     {
       return mem;
     }
       else 
     {
       throw bad_alloc();
     }
}

void operator delete(void *mem)noexcept
{
free(mem);
}

练习19.2
https://zhuanlan.zhihu.com/p/362766928

定位new表达式

class Foo
{
public:
	Foo(int val =0):_val(val){}
   
	void wirteFoo()
	{
		cout << "打印_val" << _val << "打印地址address" << this;
		cout << endl;
	}

private:
	int _val;
};

当只传入一个指针类型的实参时,定位new表达式构造对象但是不分配内存

	//创建char数组,大小为3个Foo
	char* buf = new char[sizeof(Foo) * 3];

	//实例化Foo对象,并将其位置放到buf中第一个Foo“位置处”
	Foo* pb = new(buf)Foo(0);
	//实例化Foo对象,并将其位置放到buf中第三个Foo“位置处”
	Foo* pb1 = new(buf + sizeof(Foo) * 2)Foo(1);
	//实例化Foo对象,并将其位置放到buf中第二个Foo“位置处”
	Foo *pb2 = new (buf + sizeof(Foo))Foo(2);

调用析构函数会销毁对象,但是不会释放内存

	pb->~Foo();

	pb->wirteFoo();
	pb1->wirteFoo();
	pb2->wirteFoo();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值