当前位置:网站首页>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中,所以在条用父类中的析构的时候,我们释放了两次一模一样的地址,所以肯定会报错。
边栏推荐
- 简单的线性表的顺序表示实现,以及线性表的链式表示和实现、带头节点的单向链表,C语言简单实现一些基本功能
- 安全至上:落地DevSecOps最佳实践你不得不知道的工具
- HBuilderX的下载安装和创建/运行项目
- nodejs+express实现数据库mysql的访问,并展示数据到页面上
- 持续投入商品研发,叮咚买菜赢在了供应链投入上
- boot issue
- Flask Framework Beginner-06-Add, Delete, Modify and Check the Database
- this巩固训练,从两道执行题加深理解闭包与箭头函数中的this
- esp32 releases robot battery voltage to ros2 (micro-ros+CoCube)
- 持续投入商品研发,叮咚买菜赢在了供应链投入上
猜你喜欢
随机推荐
多线程 之 JUC 学习篇章一 创建多线程的步骤
安全至上:落地DevSecOps最佳实践你不得不知道的工具
Example: 036 is a prime number
MongoDB数据接入实践
持续投入商品研发,叮咚买菜赢在了供应链投入上
SAP SD module foreground operation
v-model
什么是SVN(Subversion)?
Small Turtle Compilation Notes
Promise solves blocking synchronization and turns asynchronous into synchronous
阿里云技术专家邓青琳:云上跨可用区容灾和异地多活最佳实践
Please refer to dump files (if any exist) [date].dump, [date]-jvmRun[N].dump and [date].dumpstream.
【无标题】
C语言力扣第54题之螺旋矩阵。模拟旋转
工程制图名词解释-重点知识
LDO investigation
Quickly build a website with static files
Web APIs BOM- 操作浏览器:swiper 插件
【OpenCV】-重映射
2022 中国算力大会发布“创新先锋”优秀成果








