文章目录
- C++语言
- 1.new关键字
- 2.delete关键字
- C语言
- 1.malloc关键字
- 2.free关键字
- 区别
- 内存泄漏
- 参考博客
😊点此到文末惊喜↩︎
C++语言
1.new关键字
- 作用:C++通过new关键字动态分配内存
- 三种用法
- plain new:最朴素的new,在使用new时编译器会申请内存,然后调用类的构造函数来初始化对象,调用delete会销毁对象同时释放该对象占用的内存,并且我们可以重载new操作符。但在空间分配失败的情况下,会抛出异常std::bad_alloc
- nothrow new:在空间分配失败的情况下是不抛出异常,而是返回NULL。常用于服务器端内存不足时,不抛出异常而使程序终止,而是等待内存分配
- placement new:
- 原因:new操作符分配内存需要在堆中查找足够大的剩余空间,这个操作速度是很慢的,而且有可能出现无法分配内存的异常(空间不够)。
- 解决方式:通过重载operator new复用已分配的原始内存空间,在该内存块上调用构造函数进行创建对象,所以对象销毁的时候不需要调用delete释放空间,但必须调用析构函数销毁对象。
- 优点:用于需要反复创建并删除的对象上,可以有效降低分配释放内存的开销和碎片问题
class A
{
int m_v;
public:
A() {}
A(int v) : m_v(v) {}
A(double v) : m_v(ceil(v)) {}
};
// plain new
A* p1 = new A; //非必要情况不会调用合成的构造函数
A* p2 = new A(); //必然调用构造函数,如果没有,调用合成构造函数
A* p3 = new A(3); //调用int参数构造
A* p4 = new A(3.1); //调用double类型构造
A* p5 = new A[2]; //分配2个元素数组,非必要不初始化
A* p6 = new A[2](); //分配2个元素,初始化
A* p7 = new A[2](3); //非法调用,动态分配数组不能指定带参数的构造函数
//
delete p1;
delete p2;
delete p3;
delete p4;
delete [] p5;
delete [] p6;
// nothrow new
p1 = new(nothrow) A;
if(p1 == nullptr)
···;//等待并重试
// placement new
// 调用nothrow进行内存实际分配
char* p = new(nothrow) char[100];
// 使用placement new进行该内存的复用
long *q1 = new(p) long(100);
int *q2 = new(p) int[100/sizeof(int)];
- 原理
- new本质:调用operator new分配内存,将该内存进行转型后赋值给指针,然后调用构造函数进行赋值
- operator new本质:尝试使用malloc进行分配内存,同时进行异常处理。可以重载,
// ### 调用new
Complex *pc = new Complex(1, 2);
// ### new的源码概括性解释
Complex *pc;
try{
// 1.分配内存,实质调用malloc
void *mem = operator new(sizeof(Complex));
// 2.内存转型,赋值给指针
pc = static_cast<Complex*>(mem);
// 3.调用构造函数实例化内存(赋值)
pc->Complex::Complex(1, 2);
}catch(std::bad_alloc){
// 若allocation失败就不执行constructor
}
// ### operator new的源码概括性解释
// 第二参数保证函数不抛出异常
void *operator new(size_t size, const std::nothrow_t &){
void *p;
// 如果内存耗尽导致分配失败 (实质调用malloc)
while((p=malloc(size)) == 0){
_TRY_BEGIN
if(_callnewh(size) == 0)// 调用自定义函数进行处理
break;
_CATCH(std::bad_alloc)
return 0;
_CATCH_END
}
return p;
}
- 注意事项
- new分配的空间使用delete释放,new[] 使用 delete[]。
- 如果重载了operator new,就应该也相应的重载operator delete
2.delete关键字
- 作用:
- 释放new分配的动态内存:delete需要与new配对使用,其参数可以是指向一块内存首地址或空指针(nullptr)。不能对同一块内存多次delete,但是可以对空指针多次delete。
- 阻止编译器合成函数:C++11以上,如果没有为类编写构造函数、析构函数、拷贝构造函数、拷贝赋值运算符,以及移动拷贝函数、移动赋值运算符,编译器可能会为类合成默认的函数版本。显式使用delete,可以阻止编译器合成对应函数。
class MyObj {
public:
// 阻止编译器合成构造函数,会导致类无法实例化
MyObj() = delete;
// 阻止编译器合成拷贝构造函数,会导致类无法拷贝构造,如cin, cout
MyObj& MyObj(const MyObj &) = delete;
// 阻止合成赋值运算符,会导致类无法拷贝,如cin, cout, cerr
MyObj& operator=(const MyObj &) = delete;
...
}
// default显式告诉编译器使用编译器自动合成的函数
class MyObj {
public:
// 告诉编译器合成构造函数,作为默认构造函数,类的设计者不会实现该函数
MyObj() = default;
// 告诉编译器合成拷贝构造函数,作为默认拷贝构造函数
MyObj& MyObj(const MyObj &) = default;
// 告诉编译器合成赋值运算符
MyObj& operator=(const MyObj &) = default;
...
}
- delete的本质:先调用析构函数处理类对象,后调用operator delete函数进行内存的释放。operator delete函数本质是调用free函数
// delete的编译解释
delete pc;
pc->~Complex();// 先析构对象
operator delete(pc);// 后释放
//operator delete源码
void __cdecl operator delete(void *p)_THROW0(){
free(p);
}
- new和delete的组合使用
// 动态申请/释放一个int类型的空间
int* ptr1 = new int;
delete ptr1;
// 动态申请/释放一个int类型的空间并初始化为10
int* ptr2 = new int(10);
delete ptr2;
// 动态申请/释放10个int类型的空间
int* ptr3 = new int[10];
delete[] ptr3;
- delete是如何获知需要释放的内存(数组)大小的?
动态申请的内存块首部有cookie记录该块内存大小
C语言
1.malloc关键字
- 作用:
- 注意事项
- new分配的空间使用delete释放,new[] 使用 delete[]。
- malloc/calloc/realloc之间区别
- malloc函数:从堆上申请内存空间,必须使用memset初始化
- calloc函数:从堆上申请内存空间并初始化为0
- realloc函数:对已经存在的内存空间进行调整,如果更大会进行内存空间的延申,如果无法延申会申请新空间并拷贝和释放旧空间。如果更小会将原空间缩小。
- 使用malloc函数,calloc函数和realloc函数分配的内存空间都要使用free函数或指针参数为NULL的realloc函数来释放。?????????????????????
2.free关键字
区别
内存泄漏
什么是内存泄漏?
动态申请的资源,不使用了,也没有主动释放,就存在内存泄漏
//内存申请了没释放
int* a = (int*)malloc(sizeof(int));
int* b = new int;
//异常安全问题
int* c = new int;
fun()😕/如fun()函数抛异常,delete[] c未能执行,c没被释放
delete[] c;
1
2
3
4
5
6
7
8
内存泄漏的的危害
如果出现内存泄漏的进程正常结束,在进程结束时这些资源会自动归还系统,不会造成什么大的危害。
如果出现内存泄漏的进程正常结束(例如僵尸进程),则可用资源越来越少,系统会越来越慢,甚至卡死宕机。
需要长期运行的程序(服务器等),出现内存泄漏,系统会越来越慢,甚至卡死宕机。
如何避免?
事前预防。(如智能指针等)
事后查错。(使用泄漏检测工具等)
————————————————
版权声明:本文为CSDN博主「SimplexXx0」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/SimplexXx0/article/details/125702568
🚩点此跳转到首行↩︎
参考博客
- C++ new关键字详解
- 【C++】内存管理之new和delete
- C++中placement new操作符
- C++> delete关键字初探
- 待定引用
- 待定引用
- 待定引用
- 待定引用