zoukankan      html  css  js  c++  java
  • 使用QT进行内存管理

    Memory Management with Qt
    使用QT进行内存管理
    Garbage Collection through the Back Door
    通过后门垃圾回收
    Highly typed programming languages demand explicit (or at least implicit) creation of objects mentioning their types. They differ in how the objects are deleted: there are two approaches - direct deletion by the program or garbage collection by the language.
    高级类型的语言要求对象创建时明确的(或者至少是隐式的)声明他们的类型。他们可以通过对象是如何销毁的来区别:有两种方法——通过程序直接销毁或者通过语言的垃圾回收机制。
    Explicitly deleting languages (eg. C++, Pascal) demand that the user knows when it is best to get rid of a dynamically created object. Garbage collected languages (eg. Java, SmallTalk) try to find out when an object is no longer used and automatically reclaim the memory.
    明确的删除的语言(如,C++,Pascal)要求用户知道什么时候最好避免动态创建的对象。垃圾回收的语言(如java,Smaltalk)尝试找出什么时候一个对象不再被使用并自动的回收那部分的内存。
    Explicit deletion has the nice property that the programmer is in full control over the programs ressources - the amount of memory used and the amount and timing of CPU cycles spent on managing these ressources.
    明确的删除的好处那就是程序员可以完全控制程序或者资源——使用的内存的大小和管理这些资源花费的cpu周期的大小和数量。
    Garbage Collection on the other hand takes a lot of responsibility off the programmer by keeping track on object references inside the system and freeing memory as needed.
    另一方面垃圾回收通过在系统内部维持对象的属性的轨迹并且在必要时释放内存来分担程序员的一部分的职责

    Default C++ Memory Handling
    默认的C++的内存处理
    C++ is a language that demands that the user deletes objects explicitly. There are three important strategies on how to handle this:
    C++是一种要求用户显式的删除对象的语言。在如何处理方面有三种重要的策略:
    Let the creating object delete its child objects.
    Let the last object to handle an object delete it.
    Don't care about memory and forget about it.
    让创建的对象删除它的子对象。
    让最后的对象来控制一个对象来删除它。
    不关心内存并且忘了有这件事。

    The last strategy is called "memory leak" and usually regarded as a "bug".
    最后的策略被称为内存泄露并且常常被认为是一个‘bug’
    The real problem with C++ is to find out which of the first two strategies is right and how to implement it. There are some cases in which the creating object is deleted much earlier than the child object and in which it is hard to find out which is the last object to handle it.
    C++中的真正的问题是找出前两种策略的哪个是正确的并且如何实现它。在一些情况中创建的对象比子对象删除的早的多并且很难找出哪个是最后的对象来处理它
    Default Qt Memory Handling
    默认的QT内存处理
    Qt maintains hierarchies of objects. For widgets (visible elements) these hierarchies represent the stacking order of the widgets themselves, for non-widgets they merely express "ownership" of objects. Qt deletes child objects together with their parent object. While this takes care of 90% of memory handling problems it also brings some challenges and leaves a few aspects open.
    Qt维护了对象的分类。对widget(可视化元件)这些层次表现在widgets的压栈顺序,对非widget的他们很少表现出对象的归属。Qt把子对象和他们的父对象一起删除。这样能够处理90%的内存处理问题同时它也带来了一些机会并且一些方面的敞开。

    QPointer

    QPointer is a template class that can watch a dynamic object and updates when the object is deleted, otherwise it behaves just like a normal pointer:
    Qpointer是一个模版类,它能够监控动态对象并且在对象被删除时更新,否则它和一般的指针的表现几乎是一样的。
    QDate *mydate=new QDate(QDate::currentDate());
    QPointer<QDate> mypointer=mydata;
    mydate->year();    // -> 2005
    mypointer->year(); // -> 2005

    After deletion of the original object it starts to behave differently:
    在删了原对象之后他就开始有不同的表现了
    delete mydate;

    if(mydate==0) printf("clean pointer");
    else printf("dangling pointer");
    // -> "dangling pointer"

    if(mypointer.isNull()) printf("clean pointer");
    else printf("dangling pointer");
    // -> clean pointer

    QObjectCleanupHandler

    The cleanup handler of Qt is a further step towards automatic garbage collection. It can register several child objects and delete them all simultaniously when it itself is deleted. It also recognises automatically if any of its registered objects is deleted earlier and removes it from its list.
    Qt中的cleanup句柄是自动垃圾回收中走的更远的一步。它能够注册多个的子对象并且在他被删除的同时删除它们。它同样可以自动的发现任何他的注册的对象被提前删除并且从他的表中删除。

    This class can be used any time when objects that are not in the same hierarchy need to be deleted upon a certain event (eg. several top level windows need to be closed when a button is pressed or when another window closes).
    这个类可以在不在同一层次的对象因为一个特殊的事件(如当一个按钮被按下或者当另一个窗口被关闭的时候,几个顶层的窗口需要被关闭)被删除的任何时候使用.
    //instantiate handler
    QObjectCleanupHandler *cleaner=new QObjectCleanupHandler;
    //create some windows
    QPushButton *w;
    w=new QPushButton("Remove Me");
    w->show();
    //register first button
    cleaner->add(w);
    //if first button is pressed, it removes itself
    connect(w,SIGNAL(clicked()),w,SLOT(deleteLater()));
    //create second button with no function
    w=new QPushButton("Nothing");
    cleaner->add(w);
    w->show();
    //create third button to delete all
    w=new QPushButton("Remove All");
    cleaner->add(w);
    connect(w,SIGNAL(clicked()),cleaner,SLOT(deleteLater()));
    w->show();

    In the code above three windows containing a single button are created. If the first button ("Remove Me") is pressed, it will delete itself (via the "deleteLater" slot) and the cleanup handler will automatically remove it from its list. If the third button ("Remove All") is pressed it will delete the cleanup handler, which will in turn delete all buttons that are still open.
    在上面的三个包含了一个简单的窗体代码被创建。如果第一个按钮("Remove Me")被按下的时候,它将会删除自己(经由"deleteLater"槽)并且cleanup句柄将自动的把它从他的表中删除。如果第三个按钮("Remove All")被按下的时候,它将删除cleanup句柄,这将依次删除所有还是开着的按钮。

    Garbage Collection with Qt
    用Qt进行垃圾回收
    Sometimes objects are handed around to different other objects which all jointly own this object - so it is hard to determine when to delete this object. Fortunately with Qt it is possible to emulate garbage collection for child and parent classes that are derived from QObject.
    有时候对象被传递给了不同的拥有这个对象的其它对象,所以很难决定什么时候删除这个对象。幸运的是使用Qt,模拟为源自QObject的父子类垃圾回收将是可能的。
    There are several approaches to garbage collection. The easiest way is to implement instances counters, or one could store all owning objects. The garbage collection could be added to the class itself or handled by an outside object. Several of these methods will be developed below.
    有几种方法可以进行垃圾回收。最简单的方法是实现实例计数器,或者一个可以存放所拥有的对象。垃圾回收可以被加到一个类自身中或者被一个外部的对象处理。下面是这些方法的实现的几个例子。
    Instance Counting
    实例计数
    Instance counting is the easiest way of implementing garbage collection. For each reference made to the object the counter is increased, for each release it is decreased:
    实例计数是实现垃圾回收的最简单的方法。对每个声明,将会使该对象的计数器增加,每个释放将使其减小。
    class CountedObject
    {
        public:
            CountedObject(){ctr=0;}
            void attach(){ctr++;}
            void detach(){
                    ctr--;
                    if(ctr<=0)delete this;
            }
        private:
            int ctr;
    };

    Each object that takes ownership of the object needs to call attach when it takes ownership and detach when it releases it. So far this approach does not take advantage of Qt - a more automatic approach would be this:
    在对象他得到所有权时,每个拥有该对象的对象需要调用attach,并且在释放的时候要调用detach。到目前为止这种方法没有使用qt的先进性,更为自动的方法应该是这样的:
    class CountedObject:public QObject
    {
        public:
            CountedObject(){ctr=0;}
            void attach(QObject*o){
                    ctr++;
                    connect(o,SIGNAL(destroyed(QObject*)),this,SLOT(detach()));
            }
        public slots:
            void detach(){
                    ctr--;
                    if(ctr<=0)delete this;
            }
        private:
            int ctr;
    };

    In this code the detach() method will be called automatically when the owning object is deleted. Unfortunately this does not take into account that an owning object could call attach() twice by accident.
    在这段代码中detach()方法将会在所拥有的对象被删除的时候自动地被调用。不幸的是没有考虑到一个所拥有的对象会意外的调两次的attach()。
    Owner Collection
    所有者回收
    A more intelligent approach is to not only remember how many objects own this object, but which ones.
    更为智能的方法是不仅仅记住多少个对象拥有这个对象,而是哪个对象
    class CountedObject:public QObject
    {
        public:
            CountedObject(){}
            void attach(QObject*o){
                    //check owner for validity
                    if(o==0)return;
                    //check for duplicates
                    if(owners.contains(o))return;
                    //register
                    owners.append(o);
                    connect(o,SIGNAL(destroyed(QObject*)),this,SLOT(detach(QObject*)));
            }
        public slots:
            void detach(QObject*o){
                    //remove it
                    owners.removeAll(o);
                    //remove self after last one
                    if(owners.size()==0)delete this;
            }
        private:
            QList<QObject*>owners;
    };

    This code is finally able to protect itself against any faults caused by called attach or detach multiple times. Unfortunately it is not possible to protect the code against faults cause by not calling attach at all, since it is not possible to force C++ into telling the class how many pointers exist that point to any given object.
    这段代码最终能够在因为多次调用attach或者detach所导致的错误中保护自己了。不幸的是它不能够在根本没有调用attach的错误中保护自己,因为他没有办法强迫C++告诉类有多少指针存在指向给定的对象的指针。

    Generic Approach
    一般的方法
    It is also possible to factor this code out into its own class, so that multiple objects can be handled by the same garbage collector instance and be delete simultaniously after the last parent was deleted.
    同样也可以将这段代码提取出来放入它自己的类中,以便多个对象能够通过相同的垃圾回收实例来处理,并且通过最后的父对象被删除的刺激而删除。
    qgarbagecollector.cpp
    qgarbagecollector.h

    The code linked above can care about multiple child objects in an independent garbage collector object. All children are deleted at the same time when either the garbage collector itself or the last parent (supervisor) is deleted. The garbage collector pointer does not need to be carried around, since the instance will delete itself upon completion of its task.
    上面的代码链接能够在一个独立的垃圾回收的对象中处理多个子对象。当垃圾回收者或者最后的父对象被删除时,所有的子对象被同时删除。垃圾回收的指针不需要装载,实例在完成它的任务之后会删除它自己。

    注:代码可以在我的资源中下,也可以在下面的地址下
    原文地址: http://silmor.de/33

  • 相关阅读:
    Windows 右键添加用记事本打开的选项
    shell 脚本常用写法
    常用命令--dig
    电子表格数字式的小时化成时分秒格式
    Kaggle猫狗图像分类竞赛Baseline
    阿里巴巴用户体验研究专员暑期实习生笔试 经验分享 2019
    sysctl -w net.core.somaxconn=65535
    src/stream/ngx_stream_proxy_module.c:542: 错误:‘ngx_stream_upstream_t’没有名为‘ssl_name’的成员
    ssl.cpp:333: error: ‘SSL_set_tlsext_host_name’ was not declared in this scope
    fiddler QuickExec
  • 原文地址:https://www.cnblogs.com/zelos/p/3402891.html
Copyright © 2011-2022 走看看