当前位置:网站首页>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中,所以在条用父类中的析构的时候,我们释放了两次一模一样的地址,所以肯定会报错。
边栏推荐
- 多渠道打包
- 2022 中国算力大会发布“创新先锋”优秀成果
- Sky map coordinate system to Gaode coordinate system WGS84 to GCJ02
- C语言:学生管理系统(链表版)
- LDO investigation
- Is there any jdbc link to Youxuan database documentation and examples?
- Slipper - virtual point, shortest path
- Apache DolphinScheduler新一代分布式工作流任务调度平台实战-中
- Parquet encoding
- 实例036:算素数
猜你喜欢
随机推荐
简单的线性表的顺序表示实现,以及线性表的链式表示和实现、带头节点的单向链表,C语言简单实现一些基本功能
esp32 releases robot battery voltage to ros2 (micro-ros+CoCube)
Priority_queue element as a pointer, the overloaded operators
nodejs切换版本使用(不需要卸载重装)
阿里云技术专家邓青琳:云上跨可用区容灾和异地多活最佳实践
JS 保姆级贴心,从零教你手写实现一个防抖debounce方法
工程制图平面投影练习
KunlunBase 1.0 发布了!
【无标题】
一个注解替换synchronized关键字:分布式场景下实现方法加锁
GNSS【0】- 专题
The browser
数组_滑动窗口 | leecode刷题笔记
appium软件自动化测试框架
splice随机添加和删除的写法
Thinkphp commonly used techniques
this巩固训练,从两道执行题加深理解闭包与箭头函数中的this
C 学生管理系统_添加学生
观察者模式
SAP SD模块前台操作








