QT中手动释放堆中的对象(new 出来的)

2023-05-16

Qt内存自动释放有两个前提条件:1. 必须是QObject的派生类 2.必须指定了parent对象 即:Qt 中 父亲被删除的时候会自动销毁他的孩子。所以如果New出来的并且没有父亲。那么则需要手动删除它。需要,不然那块空间就一直占用了

 QLabel* lb=new QLabel();  

    delete (lb);  

    if(lb==NULL)  

    {  

   

    }  

    delete(this);//this是继承Qweiget基类的子控件,当new出来此控件后,想要彻底释放此子控件,需这样用delete手动释放,  

                               //用delete释放后可触发此控件类的析构函数彻底释放相关ui资源,可通过断点观察

如果是自己 new 出来的, delete 掉就好了.
如果不是new 出来的, 就不用管. qt 会自己释放掉.

QT 关闭窗口是否销毁窗口及子部件

顶层窗口调用close:应用程序销毁该窗口部件及子部件。

非顶层窗口close:关闭时只是隐藏,不会被销毁。

qt对象销毁过程delete

在C++中学习过程中,我们都知道:

  • delete 和 new 必须配对使用(一 一对应):delete少了,则内存泄露,多了麻烦更大。

Qt作为C++的库,显然是不会违背C++的前述原则的。可是:

  • 在Qt中,我们很多时候都疯狂地用new,却很少用delete,缺少的 delete 去哪儿了?!

注:本文暂不涉及智能指针(smart pointer)相关的东西,你可以考虑 Qt 智能指针学习 一文

Qt半自动的内存管理

在Qt中,以下情况下你new出的对象你可以不用亲自去delete (但你应该清楚delete在何处被Qt调用的,怎么被调用的):

  • QObject及其派生类的对象,如果其parent非0,那么其parent析构时会析构该对象(本文内容围绕这一点展开)

除此之外,有些类的对象可以接收设置一些特别的标记,比如:

  • QWidget及其派生类的对象,可以设置 Qt::WA_DeleteOnClose 标志位(当close时会析构该对象)
  • QAbstractAnimation派生类的对象,可以设置 QAbstractAnimation::DeleteWhenStopped
  • QRunnable::setAutoDelete()
  • MediaSource::setAutoDelete()
  • ...

注意:这些用法会有些陷阱,请注意看本文最后的3个小例子。

在Qt中,最基础和核心的类是:QObject 。它的魔力很大,本文只关注两点:

  • 父子关系
  • deleteLater

父子关系

在Qt中,每个 QObject 内部都有一个list,用来保存所有的 children,还有一个指针,保存自己的parent。当它自己析构时,它会将自己从parent的列表中删除,并且析构掉所有的children。

  • 注意:在 Qt 中,我们经常会遇到
    • 基类、派生类,或父类、子类。这是对于派生体系来说的,和在C++相关书中看到的完全一样,与这的parent无关
    • 父对象、子对象、父子关系。这是Qt中所特有的,也就是这儿的parent所引入的,与类的继承关系无关

建立与解除


Q_INVOKABLE QObject::QObject ( QObject * parent = 0 )  
  • 创建一个QObject对象时,如果指定了父对象,它就会将自己添加到父对象的 children 列表中

QObject::~QObject () [virtual]  
  • 当一个QObject对象析构时,它会将自己从父对象的 children 列表中移除(parent非0的话)

void QObject::setParent ( QObject * parent )  
  • 通过该函数,将自己从原父对象的children中删除,添加到新parent的children列表中

注:这三个函数都是通过一个内部私有函数来实现的,这就是


QObjectPrivate::setParent_helper(QObject *o)  

获取父、子对象

每个QObject只有一个父对象:


QObject * QObject::parent () const  

子对象可以有多个


const QObjectList & QObject::children () const  

所以可以根据条件来查找喽:


T QObject::findChild ( const QString & name = QString() ) const
QList<T> QObject::findChildren ( const QString & name = QString() ) const  

deleteLater

deleteLater 包含两层意思了

  • delete
  • later

呵呵,似乎这是废话哈。

删除自己

在去年春节前的时候吧,有人对


obj-> deleteLater()  

会像下面一样调用delete:


delete obj;  

感到不解。然后我写了这样一个C++例子:


class A
{
  public:
  A(){}
  void deleteMe()
  {
      delete this;
  }
};

int main()
{
  A * a = new A;
  a->deleteMe();
  return 0;
}   

应该不需要解释吧

later

Qt 是事件驱动的,所以发送一个删除事件到事件系统就可以啦:


void QObject::deleteLater()
{
    QCoreApplication::postEvent(this, new QEvent(QEvent::DeferredDelete));
}  

事件循环稍后看到该事件就会将其派发会这个widget:


bool QObject::event(QEvent *e)
{
    switch (e->type()) {
...
    case QEvent::DeferredDelete:
         ...  

一些例子

无关痛痒?

很简短、很熟悉的一个例子是不?但是 如果你发现对象的析构函数始终不被成功调用,会有什么感觉?


#include <QApplication>
#include <QLabel>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QLabel *label = new QLabel("Hello Qt!");
label->show();
return app.exec();
}  

这是 C++ GUI Programming with Qt 4 一书的第一个例子。我们注意到这儿的 label 既没有指定parent,也没有对其调用delete。

所以,这儿会造成内存泄露。

书中解释说,对于这种小例子,这点内存泄露不算什么。不清楚官方这个例子的意图是什么,或许是一开始就让大家用指针吧。

三种改进方式

  • 分配对象到stack而不是heap中

QLabel label("Hello Qt!");
label.show();  
  • 设置标志位,这样,当我们点击关闭按钮时,close()函数将会调用deleteLater

label->setAttribute(Qt::WA_DeleteOnClose);  
  • 动手调用delete(不就是少了一个么,我们补上还不行么)

int ret = app.exec();
delete label;
return ret;  

单独列一个吧

强化一下对前一个例子的了解


#include <QApplication>
#include <QLabel>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QLabel label("Hello Qt!");
label.show();
label.setAttribute(Qt::WA_DeleteOnClose);
return app.exec();
}  

运行正常,退出时会崩溃,因为label被close时,将会 delete 这儿label对象,但label对象却不是通过new分配到heap中的。

为了使得用户减少自己显式使用delete,Qt将delete隐藏的比较深。这样一来,不使用new为对象分配空间时,反倒需要多多小心了。

隐蔽很深?

看个小例子:这个程序退出时会直接崩溃。


#include <QtGui>
int main(int argc, char* argv[])
{
   QApplication app(argc, argv);
   QLabel label(tr"Hello Qt!");
   QWidget w;
   label.setParent(&w);
   w.show();
   return app.exec();
}  
  • 问题出在哪儿呢?因为退出时,w 比 label 先被析构,当 w 被析构时,会删除chilren列表中的对象,也就是这儿的 label。但 label 却不是通过new分配在heap中,而是在stack中,可想而知,delete 一个再stack中的对象会怎么样了。相当于

QLabel label();
delete &label;  
  • 两种改进办法:
    • 一是,将label分配到heap中

   QLabel *label = new QLabel("Hello Qt!");
   label.setParent(&w)  
  • 再一种就是,确保label先于其parent被析构(调整一下顺序),这样,label析构时将自己从父对象的列表中移除自己,w析构时,children列表中就不会有分配在stack中的对象了。

   QWidget w;
   QLabel label(tr"Hello Qt!");  

Qt 对象的父子关系的引入,简化了我们对内存的管理,但是,由于它会在你不太注意的地方调用 delete,所以,使用时还是要当心。

QT中 自己new的QSound对象如何销毁

自己delete是可以的

不过qt对于内存管理是很方便的。他可以在父对象删除时自动删除子对象,而不需要你去关心内存的释放。
所以你只要设置了父子关系就可以不用管什么时候销毁了。
把this指针传给他
QSound *snd=new QSound(this);

Qt中对象销毁的几种用法

1. 生成对象时指定了parent, 且此对象是QObject,则parent会接管此对象的销毁工作。
即只用new不用delete, 当parent在销毁时会自动将这个子对象进行合适的销毁。

由于自动销毁,至于如果使用deleteLater();这种重复删除,会不会和Qt自动销毁的机制有冲突?这个就没研究明白了。

2. 生成对象时使用了QPointer, 在删除时应使用
XX.deleteLater(); 并且之后的一条语句一定不要 用XX=NULL;(因为deleteLater()非阻塞,并非马上删除,此时如果置XX=NULL了,可能Qt发现已经是NULL将不再删除此对象,造成内存泄露)

3. 当使用普通的C++指针,请用传统的delete
if(NULL != XX) {delete XX;  XX = NULL;}

 

我们都知道C++中的new和delete是需要成对存在的,否则会导致内存泄漏。但是,在QT中,有的时候我们new出来的对象,并不需要delete也会释放掉。那么,究竟什么时候需要手动释放,什么时候不需要释放,交给QT自动释放呢?

##2.QT的自动释放机制
在QT基础 - QObject简介一文中提到:
QObject在对象树中组织自己。当你用另一个对象作为父对象创建一个QObject时,对象将自动添加到父对象的children()列表中。父母拥有对象的所有权;即它会自动删除其子析构器中的子元素。

因此,我们可以得出如下结论:
当且仅当一个对象满足如下条件:
1.该对象是QObject的派生类
2.该对象的父类不为NULL
那么,该对象的父类删除时,该对象会被自动删除,无需手动释放。

##3.结论
当且仅当一个对象满足如下条件:
1.该对象是QObject的派生类
2.该对象的父类不为NULL
那么,该对象的父类删除时,该对象会被自动删除,无需手动释放。

C/C++内存分配方式与存储区

C/C++内存分配有三种方式:
[1]从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。
[2]在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。
栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
[3]从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。
动态内存的生存期由程序员决定,使用非常灵活,但如果在堆上分配了空间,就有责任回收它,否则运行的程序会出现内存泄漏,
频繁地分配和释放不同大小的堆空间将会产生堆内碎块。


C/C++程序编译时内存分为5大存储区:
1.栈区(stack) --编译器自动分配释放,主要存放函数的参数值,局部变量值等;
2.堆区(heap) --由程序员分配释放;
3.全局区或静态区 --存放全局变量和静态变量;程序结束时由系统释放,分为全局初始化区和全局未初始化区;
4.字符常量区 --常量字符串放与此,程序结束时由系统释放;
5.程序代码区--存放函数体的二进制代码
例: //main.c
int a=0; //全局初始化区
char *p1; //全局未初始化区
void main()
{
int b; //栈
char s[]="bb"; //栈
char *p2; //栈
char *p3="123"; //其中,“123\0”常量区,p3在栈区
static int c=0; //全局区
p1=(char*)malloc(10); //10个字节区域在堆区
strcpy(p1,"123"); //"123\0"在常量区,编译器 可能 会优化为和p3的指向同一块区域



一个C程序占用的内存可分为以下几类:
(一) 栈
这是由编译器自动分配和释放的区域。主要存储函数的参数,函数的局部变量等。当 
一个函数开始执行时,该函数所需的实参,局部变量就推入栈中,该函数执行完毕 
后,之前进入栈中的参数和变量等也都出栈被释放掉。它的运行方式类似于数据结构 
中的栈。
(二) 堆
这是由程序员控制分配和释放的区域,在C里,用malloc()函数分配的空间就存在于堆 
上。在堆上分配的空间不像栈一样在某个函数执行完毕就自动释放,而是一直存在于 
整个程序的运行期间。当然,如果你不手动释放(free()函数)这些空间,在程序运行 
结束后系统也会将之自动释放。对于小程序来说可能感觉不到影响的存在,但对于大 
程序,例如一个大型游戏,就会遇到内存不够用的问题了。
(三) 全局区
C里的全局变量和静态变量存储在全局区。它们有点像堆上的空间,也是持续存在于程
序的整个运行期间,但不同的是,他们是由编译器自己控制分配和释放的。
(四) 文字常量区
例如char *c = “123456”;则”123456”为文字常量,存放于文字常量区。也由编译器 
控制分配和释放。
(五) 程序代码区
存放函数体的二进制代码。


2. 例子(一)
int a = 0; //全局区
void main()
{
int b; //栈
char s[] = "abc"; //s在栈,"abc"在文字常量区
char *p1,*p2; //栈
char *p3 = "123456"; //"123456"在常量区,p3在栈上
static int c =0; //全局区
p1 = (char *)malloc(10); //p1在栈,分配的10字节在堆
p2 = (char *)malloc(20); //p2在栈,分配的20字节在堆
strcpy(p1, "123456"); //"123456"放在常量区


//编译器可能将它与p3所指向的"123456"优化成一个地方。
}


3. 例子(二)
//返回char型指针
char *f()
{
//s数组存放于栈上
char s[4] = {'1','2','3','0'};
return s; //返回s数组的地址,但程序运行完s数组就被释放了
}
void main()
{
char *s;
s = f();
printf ("%s", s); //打印出来乱码。因为s所指向地址已经没有数据
}


还有就是函数调用时会在栈上有一系列的保留现场及传递参数的操作。 
栈的空间大小有限定,vc的缺省是2M。栈不够用的情况一般是程序中分配了大量数组和递归函数层次太 
深。有一点必须知道,当一个函数调用完返回后它会释放该函数中所有的栈空间。
栈是由编译器自动管理的,不用你操心。 
堆是动态分配内存的,并且你可以分配使用很大的内存。但是用不好会产生内存泄漏。 
并且频繁地malloc和free会产生内存碎片(有点类似磁盘碎片),因为c分配动态内存时是寻找匹配的 
内存的。而用栈则不会产生碎片。 
在栈上存取数据比通过指针在堆上存取数据快些。 
一般大家说的堆栈和栈是一样的,就是栈(stack),而说堆时才是堆heap. 
栈是先入后出的,一般是由高地址向低地址生长。 


转载的另外一篇: 


堆(heap)和栈(stack)是C/C++编程不可避免会碰到的两个基本概念。首先,这两个概念都可以在讲数据 
结构的书中找到,他们都是基本的数据结构,虽然栈更为简单一些。 
在具体的C/C++编程框架中,这两个概念并不是并行的。对底层机器代码的研究可以揭示,栈是机器系 
统提供的数据结构,而堆则是C/C++函数库提供的。 
具体地说,现代计算机(串行执行机制),都直接在代码底层支持栈的数据结构。这体现在,有专门的寄 
存器指向栈所在的地址,有专门的机器指令完成数据入栈出栈的操作。 
这种机制的特点是效率高,支持的数据有限,一般是整数,指针,浮点数等系统直接支持的数据类型, 
并不直接支持其他的数据结构。因为栈的这种特点,对栈的使用在程序中是非常频繁的。对子程序的调 
用就是直接利用栈完成的。机器的call指令里隐含了把返回地址推入栈,然后跳转至子程序地址的操 
作,而子程序中的ret指令则隐含从堆栈中弹出返回地址并跳转之的操作。C/C++中的自动变量是直接利 
用栈的例子,这也就是为什么当函数返回时,该函数的自动变量自动失效的原因。 


和栈不同,堆的数据结构并不是由系统(无论是机器系统还是操作系统)支持的,而是由函数库提供的。 
基本的malloc/realloc/free函数维护了一套内部的堆数据结构。当程序使用这些函数去获得新的内存 
空间时,这套函数首先试图从内部堆中寻找可用的内存空间,如果没有可以使用的内存空间,则试图利 
用系统调用来动态增加程序数据段的内存大小,新分配得到的空间首先被组织进内部堆中去,然后再以 
适当的形式返回给调用者。当程序释放分配的内存空间时,这片内存空间被返回内部堆结构中,可能会 
被适当的处理(比如和其他空闲空间合并成更大的空闲空间),以更适合下一次内存分配申请。这套复杂 
的分配机制实际上相当于一个内存分配的缓冲池(Cache),使用这套机制有如下若干原因: 


1. 系统调用可能不支持任意大小的内存分配。有些系统的系统调用只支持固定大小及其倍数的内存请 
求(按页分配);这样的话对于大量的小内存分类来说会造成浪费。 
2. 系统调用申请内存可能是代价昂贵的。系统调用可能涉及用户态和核心态的转换。 
3. 没有管理的内存分配在大量复杂内存的分配释放操作下很容易造成内存碎片。 


堆和栈的对比 


从以上知识可知,栈是系统提供的功能,特点是快速高效,缺点是有限制,数据不灵活;而堆是函数库 
提供的功能,特点是灵活方便,数据适应面广泛,但是效率有一定降低。栈是系统数据结构,对于进 
程/线程是唯一的;堆是函数库内部数据结构,不一定唯一。不同堆分配的内存无法互相操作。栈空间 
分静态分配和动态分配两种。静态分配是编译器完成的,比如自动变量(auto)的分配。动态分配由 
alloca函数完成。栈的动态分配无需释放(是自动的),也就没有释放函数。为可移植的程序起见,栈的 
动态分配操作是不被鼓励的!堆空间的分配总是动态的,虽然程序结束时所有的数据空间都会被释放回 
系统,但是精确的申请内存/释放内存匹配是良好程序的基本要素。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

QT中手动释放堆中的对象(new 出来的) 的相关文章

  • 重载全局new和delete

    程序代码 如下所示 xff1a span class token macro property span class token directive keyword include span span class token string
  • 浅谈重载new操作符

    new是C 43 43 里非常重要的一个关键词 xff0c 用于申请内存 初始化对象 俗话说 有借有还再借不难 xff0c 通过new向操作系统 借 到的内存用完后必然要 还 回去 xff0c 所以对应地还有一个delete操作符与new共
  • android new intent,Android:关于onNewIntent()触发机制及注意事项

    在阅读该篇日志前 xff0c 先熟悉一下Android的四种启动模式 xff0c 因为onNewIntent并不是在所有启动模式下都会执行的 一 onNewIntent 在IntentActivity中重写下列方法 xff1a onCrea
  • new和malloc的区别

    new和malloc的区别 1 new从自由存储区上分配内存 xff0c malloc从堆上分配内存 自由存储区是C 43 43 基于new操作符的一个抽象概念 xff0c 凡是通过new操作符进行内存申请 xff0c 该内存即为自由存储区
  • New Timeline的Toolbar样式设计

    最近在做新版的Timeline xff0c Toolbar Menu 的功能基本完成 xff0c 因此把截图拿出来与各位博友分享一下 新版Timeline HTML版本 主页面 xff1a 这次主要讲解一下Toolbar Menu 的功能
  • new Date() 方法到底是获取什么时间

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 1 问题 java 中 xff0c new Date 方法 获取的时间 xff0c 究竟与当前的系统时间有什么关联 xff1f 简单的时刻对应关系吗 xff1f 2 测试环
  • New Bing来了

    chatgpt免费体验入口网址 xff1a http chat xutongbao top 参考链接 xff1a https mp weixin qq com s x8RUxofqS43xkZM 5xnTAw
  • c++ new运算符是如何调用构造函数的

    文章目录 内存申请和对象构造placement new答案很简单参考链接 内存申请和对象构造 本文内容简短 xff0c 只为记录下一次思考过程 xff0c 事情起源于一句话 xff0c new操作符会调用operator new分配内存再调
  • 2022 New Year‘s Resolution

    Some Might Say 2022 New Year 39 s Resolution Some might say we are on the edge of the new era Always are they saying thi
  • set_new_handler(0)

    STL源码剖析 第45页中有一行代码set new handler 0 xff09 xff1a inline T allocate ptrdiff t size T std set new handler 0 T tmp 61 T oper
  • A new value is to be assigned to the field 'L_BOX'

    转载 xff1a https www cnblogs com aurora cj p 9353144 html DUMP A new value is to be assigned to the field 34 lt L BOX gt 3
  • QT中手动释放堆中的对象(new 出来的)

    Qt内存自动释放有两个前提条件 xff1a 1 必须是QObject的派生类 2 必须指定了parent对象 即 xff1a Qt 中 父亲被删除的时候会自动销毁他的孩子 所以如果New出来的并且没有父亲 那么则需要手动删除它 需要 xff
  • C++的new

    C 43 43 中的new其实是一个很糊弄人的术语 xff0c 它有两种不同的含义 xff0c new运算符 xff08 new operator xff09 和new函数 xff08 operator new xff09 xff0c 值得
  • MxNet系列——how_to——new_op

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com 如何创建新的操作符 网络层 本节内容描述了创建新的MXNet操作符 xff08 或网络 xff09 的过程 我们已经尽了最大努
  • new ScriptEngineManager().getEngineByName(“js“)返回null

    问题出现的场景 xff1a 本地开发和生产环境都没问题 xff0c 测试环境 用的docker 报空指针 new ScriptEngineManager getEngineByName 34 js 34 返回null js替换 JavaSc
  • c++中 new的使用方法

    c 43 43 中 xff0c new的用法很灵活 xff0c 这里进行了简单的总结 1 new 分配这种类型的一个大小的内存空间 并以括号中的值来初始化这个变量 2 new 分配这种类型的n个大小的内存空间 并用默认构造函数来初始化这些变
  • nginx: [emerg] BIO_new_file("/etc/nginx/ssl_key/server.crt") failed (SSL: error:02001002:syste

    Centos 7 5 nginx 43 web集群配置https报错 报错信息 root 64 lb01 conf d nginx t nginx emerg BIO new file 34 etc nginx ssl key server
  • c++new操作符笔记

    c 43 43 new语句 功能 xff1a 堆区开辟一组数据 语法 xff1a new 数据类型 注意点 xff1a new创建的数据会返回该数据对应的类型指针 xff0c 另外堆区开辟的数据由程序员手动释放
  • virtual,override,new ,extern,abstract修饰符

    方法定义中可以使用的修饰符有 a new b public c protected d internal e private f static g virtual h override i extern j abstract 对于virtu
  • 20个常见的Java错误以及规避方法

    原文 50 Common Java Errors and How to Avoid Them Part 1 作者 Angela Stringfellow 翻译 雁惊寒 译者注 本文介绍了20个常见的Java编译器错误 每种错误都包含了代码片

随机推荐

  • c#中中读取嵌入和使用资源文件的方法

    Dotnet中嵌入资源 xff08 位图 图标或光标等 xff09 有两种方式 xff0c 一是直接把资源文件加入到项目 xff0c 作为嵌入资源 xff0c 在代码中通过Assembly的GetManifestResourceStream
  • c#中英文切换实例

    1 创建两个资源文件 Resource en US resx Resource zh CN resx 注意中间部分每种语言文件名固定 xff0c 后缀名是 resx 首部分是自定义的名字 2 创建读写工具类 上面两个资源文件都是在Utili
  • TCP/IP协议讲的明明白白

    从字面意义上讲 xff0c 有人可能会认为 TCP IP 是指 TCP 和 IP 两种协议 实际生活当中有时也确实就是指这两种协议 然而在很多情况下 xff0c 它只是利用 IP 进行通信时所必须用到的协议群的统称 具体来说 xff0c I
  • TCP/IP协议与Http协议的区别详解

    TPC IP协议是传输层协议 xff0c 主要解决数据如何在网络中传输 xff0c 而HTTP是应用层协议 xff0c 主要解决如何包装数据 关于TCP IP和HTTP协议的关系 xff0c 网络有一段比较容易理解的介绍 xff1a 我们在
  • C#中使用MD5对用户密码加密与解密

    C 中常涉及到对用户密码的加密于解密的算法 xff0c 其中使用MD5加密是最常见的的实现方式 本文总结了通用的算法并结合了自己的一点小经验 xff0c 分享给大家 一 使用16位 32位 64位MD5方法对用户名加密 1 xff09 16
  • C#中修改文件或文件夹的权限,为指定用户、用户组添加完全控制权限

    写在前面 在windows系统中 xff0c c盘中的目录权限比较高 xff0c 有时制作安装包的时候 xff0c 默认的安装路径就是在c盘 xff0c 但对运行可执行文件 xff0c 有时候需要为其添加完全控制权限 xff0c 或者读写权
  • C#使用SafeNet的开发狗和超级狗加密使用方法

    1 在安装光盘中选择Windows文件夹 xff0c 单击Setup exe执行安装程序 xff0c 安装过程默认选择 xff0c 单击下一步即可 2 安装完毕后插入超级狗 xff0c 在菜单栏中打开 超级狗开发商向导 xff0c 选择下载
  • Keil5 新建工程编译后Download按钮变灰

    Keil5 新建工程编译后Download按钮变灰 百度看到很多文章解决变灰方法为 这个主要目的是生成 HEX文件 xff0c 但有时候当你在线下载时点了Creat HEX File 并进行编译后 Download按钮依然呈现灰色 此时问题
  • C# SQLite 数据库操作语句与文件视图管理器

    sqlite数据库视图管理器 SQLiteSpy是一款专业的SQLite数据库管理 xff0c 主要用于读取sqlite数据库 xff0c 建立新的SQL查询 xff0c 视图 xff0c 复制和删除表 编辑单元格 xff0c 以及查看索引
  • C#JSON与XML相互转换

    using System using System Collections Generic using System Linq using System Text using System Xml using Newtonsoft Json
  • 让使用SQLite的.NET应用自适应32位/64位系统

    Windows 7 64 bit 刚扩到4G内存 果断换64位的 那速度杠杠的 Microsoft Visual Studio 2010 Ultimate 32bit 在64位系统里运行正常 sqlite netFx40 setup bun
  • WinForm 布局控件“WeifenLuo.WinFormsUI.Docking“的使用

    本篇介绍Winform程序开发中的布局界面的设计 xff0c 介绍如何在我的共享软件中使用布局控件 34 WeifenLuo WinFormsUI Docking 34 布局控件 34 WeifenLuo WinFormsUI Dockin
  • C#中JSON和对象之间互相转换功能示例

    本文实例讲述了C 实现JSON和对象之间互相转换功能 分享给大家供大家参考 xff0c 具体如下 xff1a 1 首先是声明用户信息对象 xff0c DataContract修饰类 xff0c 表示可以被解析成JSON xff0c Data
  • C#使用DataContractJsonSerializer来进行JSON解析

    在使用DataContractJsonSerializer进行解析之前 xff0c 我们首先需要将两个包引入进来 xff1a using System Runtime Serialization using System Runtime S
  • 步进电机驱动器脉冲频率确定 步进电机驱动器

    1 步进电机为什么要配步进电机驱动器才能工作 xff1f 步进电机作为一种控制精密位移及大范围调速专用的电机 它的旋转是以自身固有的步距角角 xff08 转子与定子的机械结构所决定 xff09 一步一步运行的 其特点是每旋转一步 xff0c
  • MFC添加自定义消息及重写消息过程

    由于MFC中无法通过类向导来自定义消息 xff0c 所以需要手动添加 xff0c 主要过程如下 xff1a 本文基于vs2008下通过线程实现数据实时更新的对话框运用程序 1 定义消息 xff08 Resource h文件中 xff09 x
  • C#操作注册表方法

    1 xff1a 要操作注册表 xff0c 我们必须要引入必要的命名空间 xff1a using Microsoft Win32 在这个命名空间里面包含了许多注册表相关的类 xff0c 足够我们使用了 2 xff1a 命名空间里面提供了一个类
  • 怎样测试ESP8266wifi模块?

    这里测试的方法是用USB TTL转换电路进行的测试 接线图如下所示 xff1a ESP8266引脚图如下 xff1a 因为ESP8266需要3 3V电压供电 xff0c 所以USB TTL的3 3V电压 xff0c GND分别与ESP826
  • Qt信号与槽机制

    一 简介 就我个人来理解 xff0c 信号槽机制与Windows下消息机制类似 xff0c 消息机制是基于回调函数 xff0c Qt中用信号与槽来代替函数指针 xff0c 使程序更安全简洁 信号和槽机制是 Qt 的核心机制 xff0c 可以
  • QT中手动释放堆中的对象(new 出来的)

    Qt内存自动释放有两个前提条件 xff1a 1 必须是QObject的派生类 2 必须指定了parent对象 即 xff1a Qt 中 父亲被删除的时候会自动销毁他的孩子 所以如果New出来的并且没有父亲 那么则需要手动删除它 需要 xff