目录
一,C/C++内存分布
二,内存管理方式
三,operator new/operator delete函数(重点)
四,new/delete实现原理
五,定位new表达式(placement-new)(了解)
附
一,C/C++内存分布
二,内存管理方式
C语言中动态内存管理方式
C++内存管理方式
//new/delete内置类型
int main()
{
//动态申请一个int类型的空间
int* ptr1 = new int;
//动态申请一个int类型的空间,并赋值10
int* ptr2 = new int(10);
//动态申请10个int类型的空间
int* ptr3 = new int[10];
delete ptr1;
delete ptr2;
delete[] ptr3;
return 0;
}
//new/delete自定义类型
class A
{
public:
A(int a = 0)
:_a(a)
{
cout << "A():" << this << endl;
}
~A()
{
cout << "~A():" << this << endl;
}
private:
int _a;
};
int main()
{
//申请一个A类型的空间
A* ptr1 = (A*)malloc(sizeof(A));
free(ptr1);
//申请10个A类型的空间
A* ptr2 = (A*)malloc(sizeof(A) * 10);
free(ptr2);
//申请一个A类型的空间
A* ptr3 = new A; //或带初始化值new A(10)
delete ptr3;
//申请10个A类型的空间
A* ptr4 = new A[10];
delete[] ptr4;
return 0;
}
三,operator new/operator delete函数(重点)
operator new/operator delete函数
//new与malloc区别
int main()
{
char* p1 = (char*)malloc((size_t)2 * 1024 * 1024 * 1024);
//检查p1
if (p1 == NULL)
perror("p1");
try
{
char* p2 = new char[0x7fffffff]; // 抛异常,捕获异常位置
}
catch (const exception& e)
{
cout << e.what() << endl;
}
return 0;
}
注:
operator new/operator delete类专属重载(了解)
struct ListNode
{
ListNode(int data = 0)
:_next(nullptr)
,_data(data)
{}
ListNode* _next;
int _data;
//类专属重载
//new ListNode申请空间,就会调用此处类专属重载
void* operator new(size_t n)
{
++_count;
return ::operator new(n); //::是避免自己调用自己,::前为空则为调用全局
}
void operator delete(void* p)
{
--_count;
return ::operator delete(p);
}
static int _count;
};
int ListNode::_count = 0;
struct ListNode* removeElements(ListNode* head, int val)
{
ListNode* prev = head;
ListNode* cur = head;
while (cur)
{
if (cur->_data == val)
{
prev->_next = cur->_next;
delete cur;
cur = prev->_next;
}
else
{
prev = cur;
cur = cur->_next;
}
}
return head;
}
int main()
{
//创建时先申请空间,在构造函数
ListNode* node1 = new ListNode(1);
ListNode* node2 = new ListNode(2);
ListNode* node3 = new ListNode(3);
ListNode* node4 = new ListNode(2);
ListNode* node5 = new ListNode(5);
node1->_next = node2;
node2->_next = node3;
node3->_next = node4;
node4->_next = node5;
removeElements(node1, 2);
cout << ListNode::_count << endl;
return 0;
}
四,new/delete实现原理
内置类型
自定义类型
new原理
delete原理
new T[N]原理
delete[]原理
class Stack
{
public:
Stack(int capacity = 4)
:_a(new int[capacity])
,_size(0)
,_capacity(capacity)
{
cout << "Stack():" << this << endl;
}
~Stack()
{
delete _a;
_size = _capacity = 0;
cout << "~Stack():" << this << endl;
}
private:
int* _a;
int _size;
int _capacity;
};
//先在栈上main内,开辟Stack大小的空间
//在调用构造函数,在堆上开辟16字节大小空间给_a,在初始化_size/_capacity
//最后main结束时,调用析构函数,销毁堆上开辟16字节空间,_size/_capacity赋零
int main()
{
Stack st;
return 0;
}
//先在堆上开辟Stack大小空间给main上的指针p
//在开辟Stack空间时,调用构造函数,再在堆上开辟16字节大小空间给_a,在初始化_size/_capacity
//在delete时,调用析构函数,销毁堆上开辟16字节空间,_size/_capacity赋零,在释放堆上的Stack空间
int main()
{
Stack* p = new Stack;
delete p;
return 0;
}
class A
{
public:
A(int a = 0)
:_a(a)
{
cout << "A():" << this << endl;
}
A(const A& a)
{
_a = a._a;
cout << "A(const A& a)" << this << endl;
}
A& operator = (const A& a)
{
_a = a._a;
cout << "A& operator = (const A& a)" << this << endl;
return *this;
}
~A()
{
cout << "~A():" << this << endl;
}
private:
int _a;
};
int main()
{
A a[5]; //调用5次构造
A* p1 = new A[5]; //调用5次构造
for (int i = 0; i < 5; i++)
{
*(p1 + i) = a[i]; //调用5次赋值重载
}
cout << endl;
return 0;
}
int main()
{
A a[5]; //调用5次构造
A* p1 = (A*)malloc(sizeof(A) * 5);
cout << endl;
for (int i = 0; i < 5; i++)
{
//也称replacement-new
new(p1 + i) A(a[i]); //调用5次拷贝构造
}
cout << endl;
return 0;
}
五,定位new表达式(placement-new)(了解)
定位new表达式,是在已分配的原始内存空间中调用构造函数初始化一个对象;
实际中一般配合内存池使用,因为内存池分配出的内存没有初始化,所以如是自定义类型对象,需使用new的定义表达式进行显示调构造函数进行初始化;
格式:
class A
{
public:
A(int a = 0, int val = 0)
:_a(a)
,_val(val)
{
cout << "A():" << this << endl;
}
~A()
{
cout << "~A():" << this << endl;
}
private:
int _a;
int _val;
};
int main()
{
A* p = (A*)malloc(sizeof(A));
new(p) A(1,2);
return 0;
}
附
malloc/free和new/delete共同点
malloc/free和new/delete不同点
内存泄露
内存泄露分类(了解)
避免内存泄露
注:进程正常结束,都会释放;僵死进程、长期运行的服务器程序、物联网设备等不会释放;