当前位置:网站首页>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 中国算力大会发布“创新先锋”优秀成果
ASP.NET 获取数据库的数据并写入到excel表格中
esp32发布机器人电池电压到ros2(micro-ros+CoCube)
Sticker Spelling - Memory Search / Shape Pressure DP
Flink jdbc connector 源码改造sink之 clickhouse多节点轮询写与性能分析
实例037:排序
一个注解替换synchronized关键字:分布式场景下实现方法加锁
nodejs+npm的安装与配置
Snake game bug analysis and function expansion
FileNotFoundException: This file can not be opened as a file descriptor; it is probably compressed
nodejs切换版本使用(不需要卸载重装)
ThreadLocal
【日志框架】
Example 037: Sorting
this巩固训练,从两道执行题加深理解闭包与箭头函数中的this
DDTL: Domain Transfer Learning at a Distance
nodejs+express实现数据库mysql的访问,并展示数据到页面上
工程制图平面投影练习
VR panorama shooting online exhibition hall, 3D panorama brings you an immersive experience
实例035:设置输出颜色