学习笔记:c++ new&delete关键字及其自定义

文章目录

  • 一.new运算符说明
    • 1.作用
    • 2.标准库函数
    • 3.运行原理:
    • 4.常见用法:
    • 5.size_t如何传递
  • 二.delete函数
    • 1.作用
    • 2.标准库函数
    • 3.运行原理:
    • 4.常见用法:
  • 三.自定义new和delete
    • 1.自定义规范:
    • 2.代码示例
    • 3.测试结果
  • 4.参考文献:

一.new运算符说明

1.作用

  • 动态申请内存

2.标准库函数

//会抛异常版本:
void *operator new(size_t);  //分配一个对象
void *operator new[](size_t);//分配一个数组
//不会抛异常版本:
void *operator new(size_t,nothrow_t&) noexcept;
void *operator new[](size_t,nothrow_t&) noexcept;

3.运行原理:

  • 1.通过malloc分配size_t参数指定大小的内存;
  • 2.对这块内存进行初始化(类的构造,基本类型初始化或者清0);

4.常见用法:

struct A
{
	int _val;
};
A*p = new A;                   //方式一
A *p = new A();                //方式二
A *pArray = new A[10];         //方式三
void *pMem = malloc(sizeof(A));//方式四
A *p = new(pMem) A;
  • 第一种方式申请内存空间后不会清零,如果未对变量做初始化就直接使用,存在脏数据风险;
  • 第二种方式相比第一种增加了(),这会导致在执行完内存分配后,系统会对内存进行清零,弊端是内存清零必然会损耗性能。
  • 第三种方式是用来创建对象数组的,不多说;
  • 最后一种是placement new的写法,这种写法的特点是:
    ①需要先通过malloc等函数申请到所需要大小的内存空间;
    ②通过void *operator new(size_t,void*)的这种placement new的写法,直接在malloc申请到的内存空间进行构造或者初始化;
    这种申请方式一个很显然的优势在于内存的重复利用,如果使用场景中存在一个对象需要频繁创建和销毁,推荐使用这种方式。

    5.size_t如何传递

  • 我们可以看到new操作符的定义中第一个参数是size_t类型的,但是我们实际使用中并没有去指定参数,那这个参数是怎么传递下去的呢?实际上当编译器在处理operator new时,会将存储指定指定对象内存大小传递给new函数的第一个参数。同样的,当调用operator new[]时,编译器会将存储指定对象数组所需的内存空间传递到new[]函数的第一个参数。
  • 后面我们会看到如果我们自定义了new操作符,并且带有额外参数,调用时传递的第一个参数实际上会传递到operator new(size_t,args…)函数的第二个形参里面去。

二.delete函数

1.作用

  • 释放通过new动态申请的内存空间,和new配套使用;

2.标准库函数

//会抛异常版本
void operaor delete(void *pObj);    //释放对象所占用的空间
void operator delete[](void *pArrayObj); //释放对象数组所占用的空间
//不会抛异常版本
void operator delete(void *pObj, nothrow_t&) noexcept;
void operator delete[](void *pArrayObj, nothrow_t&) noexcept;

3.运行原理:

  • 1.调用对象的析构函数;
  • 2.释放空间;

4.常见用法:

struct A
{
	int _val;
}
A *p = new A;
delete(p);      //释放单个对象
A *pArray = new A[10];
delete[](pArray);//释放对象数组

三.自定义new和delete

1.自定义规范:

operator new/delete进行自定义可以实现为类的方法或者全局方法。
如果在类的方法中自定义了operator new/delete,则在new该对象时会优先调用类中的自定义方法。如果全局也有自定义的接口,则可以通过使用限定符::来调用全局的自定义接口。

2.代码示例

#include 
#include 
#include 
#include 
#include 

void *operator new(size_t size)
{
    std::cout << "global new enter" << std::endl;
    return malloc(size);
}

void *operator new[](size_t size)
{
    std::cout << "global new array enter" << std::endl;
    return malloc(size);
}

void operator delete(void *pObj)
{
    std::cout << "global delete enter" << std::endl;
    free(pObj);
}

void operator delete[](void *pObjArray)
{
    std::cout << "global delete array enter" << std::endl;
    free(pObjArray);
}


class MemoryDemo
{
public:
    MemoryDemo() = default;
    ~MemoryDemo() = default;

    void* operator new(size_t size)
    {
        std::cout << "new enter" << std::endl;
        return malloc(size);
    }
    
    void *operator new[](size_t size)
    {
        std::cout << "new array enter" << std::endl;
        return malloc(size);
    }

    void *operator new(size_t size, int mode)
    {
        std::cout << "new with mode:" <

3.测试结果

学习笔记:c++ new&delete关键字及其自定义_第1张图片

4.参考文献:

【Primer C++ 第五版】

你可能感兴趣的:(C++,c++,学习)