当前位置:网站首页>Qt中对象树的机制介绍以及底层实现,各种结果分析:(以及自己写容易犯错的点)
Qt中对象树的机制介绍以及底层实现,各种结果分析:(以及自己写容易犯错的点)
2022-08-04 01:44:00 【lhb2998658795】
1对象树机制:
在创建QObject对象的时候,可以提供一个父对象,我们创建的这个QObject对象的时候会自动添加到其父对象的children()列表。当父对象析构的时候,这个列表的所有对象都会被析构。
2Qt中高效且简易的内存回收机制的源码剖析及底层实现:
#include <iostream>
#include <list>
using namespace std;
class Object;
typedef list<Object*> Children;
class Object
{
public:
Children children;
Object(Object* parent=nullptr)
{
if(parent!=nullptr){
parent->children.push_back(this);
}
}
virtual ~Object()
{
for(auto it=children.begin();it!=children.end();it++){
delete *it;
}
}
};
class A:public Object
{
public:
A(Object* parent=nullptr)
{
if(parent!=nullptr){
parent->children.push_back(this);
}
cout<<"A的构造"<<endl;
}
~A()
{
cout<<"A的析构"<<endl;
}
};
int main()
{
Object obj;
A* a=new A(&obj);
return 0;
}
3.自己写的时候注意点:
3.1父类中的析构一定要加virtual形成多态,不然即使A中的地址是被释放了,但是释放的类型是Object的类型,并不会条用A中的析构,这样就很危险,如果当A中有一个指针的时候,就没法释放,造成内存泄漏,而且此时因为a的地址已经被隐式强转了,所以再次删除删除的是Object类型,所以Object类型会被调用两次析构。
#include <iostream>
#include <list>
using namespace std;
class Object;
typedef list<Object*> Children;
class Object
{
public:
Children children;
Object(Object* parent=nullptr)
{
if(parent!=nullptr){
parent->children.push_back(this);
}
}
~Object()
{
for(auto it=children.begin();it!=children.end();it++){
delete *it;
*it=nullptr;
}
cout<<"Object的析构"<<endl;
}
};
class A:public Object
{
public:
A(Object* parent=nullptr)
{
if(parent!=nullptr){
parent->children.push_back(this);
}
cout<<"A的构造"<<endl;
}
~A()
{
cout<<"A的析构"<<endl;
}
};
int main()
{
Object obj(nullptr);
A* a=new A(&obj);
return 0;
}
结果图:
3.2这是我当时自己犯的错误,代码如下:
#include <iostream>
#include <list>
using namespace std;
class Object;
typedef list<Object*> Children;
class Object
{
public:
Children children;
Object(Object* parent)
{
if(parent!=nullptr){
parent->children.push_back(this);
}
}
virtual ~Object()
{
for(auto it=children.begin();it!=children.end();it++){
delete *it;
*it=nullptr;
}
cout<<"Object的析构"<<endl;
}
};
class A:public Object
{
public:
A(Object* parent=nullptr):Object(parent)
{
if(parent!=nullptr){
parent->children.push_back(this);
}
cout<<"A的构造"<<endl;
}
~A()
{
cout<<"A的析构"<<endl;
}
};
int main()
{
Object obj(nullptr);
A* a=new A(&obj);
return 0;
}
结果图:
3.2.1分析:
如图所示:当父类调用过一次后,删除了Object的类型的a的地址,按照我们上面的理解一个还会再调用一次析构,但是当析构过一次后,它直接报错了,这是为什么呢?当我们 在A中进行初始化的时候,如果按照开头我们写的那种正确方法,其实是给parent初始化为nullptr,但是当我们3.2这种写法的时候,初始化的并不是nullptr,而是a的地址,所以我们在父类中也将a中的地址放进了list中,在A中也将a的地址放进了list中,所以在条用父类中的析构的时候,我们释放了两次一模一样的地址,所以肯定会报错。
边栏推荐
猜你喜欢
5. Scrapy middleware & distributed crawler
工程制图平面投影练习
nodejs安装及环境配置
What is SVN (Subversion)?
实例041:类的方法与变量
OpenCV如何实现Sobel边缘检测
通用的测试用例编写大全(登录测试/web测试等)
Deng Qinglin, Alibaba Cloud Technical Expert: Best Practices for Disaster Recovery across Availability Zones and Multiple Lives in Different Locations on the Cloud
一篇文章看懂JS闭包,从执行上下文角度解析有趣的闭包
Flutter3.0线程——四步教你如何全方位了解(事件队列)
随机推荐
【无标题】
How to copy baby from Taobao (or Tmall store) through API interface to Pinduoduo interface code docking tutorial
Web APIs BOM- 操作浏览器:swiper 插件
html select tag assignment database query result
哎,又跟HR在小群吵了一架!
Thinkphp commonly used techniques
Intranet penetration - application
数组_滑动窗口 | leecode刷题笔记
【QT小记】QT中信号和槽的基本使用
nodejs 安装多版本 版本切换
Flask框架初学-05-命令管理Manager及数据库的使用
Use nodejs switch version (no need to uninstall and reinstall)
持续投入商品研发,叮咚买菜赢在了供应链投入上
如何用C语言代码实现商品管理系统开发
Apache DolphinScheduler新一代分布式工作流任务调度平台实战-中
工程制图平面投影练习
JS 从零教你手写节流throttle
nodejs切换版本使用(不需要卸载重装)
Flask Framework Beginner-06-Add, Delete, Modify and Check the Database
Small Turtle Compilation Notes