析构函数的调用时机
- 栈对象在当前栈作用域被释放时自动被释放,且调用析构函数
- 堆对象需要手动delete,才能被释放,和调用析构函数
#include<iostream>
class Entity22 {
public:
int x;
Entity22() {
std::cout << "Create Entity" << std::endl;
}
~Entity22() {
std::cout << "Destroy Entity" << std::endl;
}
};
int* CreateArray() {
//变量在栈中创建,这样的写法是错误的❌️
//int Arr[50];
//堆变量可以return给外部
int* Arr = new int[50];
return Arr;
//方法结束,方法栈被释放,方法栈中变量也被释放了,即便return也不能被外部调用,而堆中对象可以
}
void createObj() {
//栈对象,在当前方法执行完成后,当前方法作用域栈自动被释放,包括此对象,且析构函数自动被执行
Entity22* ent;
//堆对象,在当前方法执行完成后,当前方法作用域栈自动被释放,但此对象不在栈中,在堆中,不被释放,析构函数不被执行
//当手动delete堆对象的时候,才会释放堆中对象,其析构函数才会执行
Entity22* entity = new Entity22();
std::cin.get();
delete entity;
}
//如果栈上的变量会自动消失,那他有什么用呢?有没有其他办法,让他用在好的方面?
//答案是有的。他在很多方面都非常有用,可以帮助我们自动化代码
//eg: 其中我们可以做的一件事是,比如说利用类的作用域来实现的,像是智能指针:smart_ptr,或是unique_ptr,这是一个作用域指针
//或者像作用域锁。。。。。。有很多例子
//最简单的例子就是作用域指针了,它的本质就是一个类,是一个指针的包装器,在构造时再堆上分配指针,然后析构时删除指针。
//我们可以自动化这个new和delete。
//这就是一个简单的作用域指针
class ScopePtr {
private:
Entity22* m_Ptr;
public:
ScopePtr(Entity22* ptr):m_Ptr(ptr) {}
~ScopePtr() {
delete m_Ptr;
}
};
int main() {
CreateArray();
createObj();
//e是分配在栈上的,当e被销毁时,调用析构函数,Entity22指针也会被销毁
//这种可以自动构造、自动析构、离开作用域之后就自动销毁的栈变量是非常有用的
{
ScopePtr e(new Entity22());
}
}