当前位置:网站首页>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中,所以在条用父类中的析构的时候,我们释放了两次一模一样的地址,所以肯定会报错。
边栏推荐
猜你喜欢
【store商城项目01】环境准备以及测试
Analysis of usage scenarios of mutex, read-write lock, spin lock, and atomic operation instructions xaddl and cmpxchg
splice随机添加和删除的写法
Slipper —— 虚点,最短路
谁说程序员不懂浪漫,表白代码来啦~
SAP SD module foreground operation
Observability:你所需要知道的关于 Syslog 的一些知识
Continuing to invest in product research and development, Dingdong Maicai wins in supply chain investment
实例040:逆序列表
Use of lombok annotation @RequiredArgsConstructor
随机推荐
【store商城项目01】环境准备以及测试
循环绕过问题
Web APIs BOM - operating browser: swiper plug-in
工程制图名词解释-重点知识
FeatureNotFound( bs4.FeatureNotFound: Couldn't find a tree builder with the features you requested:
实例037:排序
Use nodejs switch version (no need to uninstall and reinstall)
MongoDB数据接入实践
Snake game bug analysis and function expansion
Continuing to invest in product research and development, Dingdong Maicai wins in supply chain investment
C 学生管理系统 显示链表信息、删除链表
持续投入商品研发,叮咚买菜赢在了供应链投入上
GraphQL背后处理及执行过程是什么
【Untitled】
实例040:逆序列表
谁说程序员不懂浪漫,表白代码来啦~
Example 035: Setting the output color
GNSS【0】- 专题
Please refer to dump files (if any exist) [date].dump, [date]-jvmRun[N].dump and [date].dumpstream.
Download install and create/run project for HBuilderX