冲突的实例化 - 内存泄漏?

时间:2012-06-13 01:20:04

标签: c++ qt memory memory-leaks

我一直潜伏着这些问题并且学到了很多东西,但最近我遇到了一个我不理解的问题。我正在使用Qt,需要在各种类方法中创建/替换QMovie对象(最终在QLabel中设置)。我使用new关键字定义了对象。因此在标题中我有

QMovie * movie;

为简单起见,我将把等效代码放在一个方法中。这相当于两行代码

QMovie * movie = new QMovie(QByteArray1,this);
QMovie * movie = new QMovie(QByteArray2,this);

这有效(我不知道为什么),但由于它是重复操作,我担心内存泄漏。似乎第二个定义成功替换了第一个定义,但由于可能它们每个都有不同的指针,我不知道如何删除指向第一个定义的指针。我在类析构函数中删除了电影,但不知道它是否会删除所有内容。有人知道这里发生了什么吗?

P.S。我这样做是因为使用QBovteArray(从Web下载)中使用数据创建QMovie对象的唯一方法(我在Qt中找到)是使用QMovie构造函数。如果我只想用文件中的新数据替换当前的电影数据,我可以使用方法

movie->setFileName(fileName);

但使用二进制数据时这不是一个选项。注意:QMovie还有一个构造函数,它有一个文件名而不是QByteArray作为参数。使用文件名也可以使用上面的代码,更容易测试。

任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:2)

一般来说,如果QObject派生的任何内容都包含在QObject s的层次结构中,则在父代被破坏时会自动销毁它们。在您的情况下,您通过构造函数给QMovie父项,因此应该为您进行清理。如果你想确认,从QMovie派生一个类,实现一个打印消息的析构函数,并确保在你期望的时候调用它(即当父节点被破坏时)。

答案 1 :(得分:1)

在C中这样做的惯用方法是:

  1. 将指针初始化为零。

  2. 在分配给它之前,free()旧指针指向的对象。你不需要来检查零:零指针上的free()是一个安全的无操作。

  3. 当指针超出范围时,
  4. free()对象。

  5. 在Qt中这样做的惯用方法甚至更简单。

    1. 使用QSharedPointer<>QScopedPointer<>。当它超出范围时,它会自动删除指向的对象。

      • 如果只有一个指针拥有该对象,请使用QScopedPointer。当它超出范围时,它将删除指向的对象。这类似于std::auto_ptr

      • 对于共享所有权,请使用QSharedPointer。当指向它的最后一个QSharedPointer超出范围/被销毁时,它将删除指向的对象。

    2. 对于QScopedPointer,使用reset(T*other)方法为指针指定新值。对于QSharedPointer,您只能为其分配其他共享指针,例如QSharedPointer a = QSharedPointer(new Class);

    3. 在任何一种情况下,任何先前指向的对象都将被删除。

      因此:

      class MyClass {
        QScopedPointer<QMovie> movie1;
        QSharedPointer<QMovie> movie2;
      public:
        MyClass {} // note: no need for any special initialization
        void method() {
          movie1.reset(new QMovie(...));
          movie2 = QSharedPointer(new QMovie(...));
        }
      };
      

      这是完全安全的。您可以根据需要随时调用MyClass::method(),无内存泄漏。在任何时候,MyClass都会保留最多两个QMovie对象。

答案 2 :(得分:0)

QMovie * movie = new QMovie(QByteArray1,this);
QMovie * movie = new QMovie(QByteArray2,this);

如果这两行在同一个.cc文件中,则会出现重新定义错误。如果这两行是在单独的.cc文件中,那么在构建可执行文件时,您将收到多重定义错误。但是,你的问题有这样的措辞:

  

我正在使用Qt,需要在各种类方法中创建/替换QMovie对象(最终在QLabel中设置)

如果QMovie对象驻留在不同的类中,则没有内存泄漏,因为每个类的指针都与另一个类不同。

但是,如果您的意图是所有类都引用相同的QMovie实例,则需要找到将实例传递给每个对象的方法。或者,您可以将它们全部引用到同一个(即使用单例模式)。