代码之家  ›  专栏  ›  技术社区  ›  mimo

如何正确销毁指向像素数据的指针?

  •  1
  • mimo  · 技术社区  · 9 年前

    在控制窗口的主类中,我有一个函数,其中 pixmapItem 是 QGraphicsPixmapItem* 在类标题中定义:

    void updateDisplay() {
        uchar *data = new ...; // array of pixel data
        ...
        QImage image = QImage(data, width, height,
                              width, QImage::Format_Indexed8);
    
        pixmapItem->setPixmap(QPixmap::fromImage(image));
    }
    

    data 什么时候不再需要?“不再需要”意味着上面的函数或我的类中的另一个函数将像素映射设置为另一个图像。

    我已经看到QImage有清理功能,可能会有所帮助,但文档中并没有明确说明如何使用它们以及如何传递参数,例如要删除的图像的数据指针。

    5 回复  |  直到 9 年前
        1
  •  3
  •   Matteo Italia    9 年前

    当 QImage 被销毁;如上面@JeremyFriesner所示,可以通过定义 奇玛格 实例,并在其外部分配/释放数据。

    然而,为什么要费心做这些工作呢?那个 奇玛格 构造器的存在是为了适应复杂的用例,其中您已经有来自其他来源的像素数据,或者您需要将其保存一段“奇怪”的生命周期。

    相反,您的情况更简单,像素数据与 奇玛格 ,所以最好让它自己为像素分配内存;这样,您可以确保它的大小和对齐正确,并且它由 奇玛格 例子之后 奇玛格 对象时,可以使用 bits 方法,并使用它执行任何您想要的操作。

    这样,您的代码将简单地变成:

    void updateDisplay() {
        QImage image = QImage(width, height,
                              width, QImage::Format_Indexed8);
        uchar *data = image.bits();
        ... 
    
        pixmapItem->setPixmap(QPixmap::fromImage(image));
    }
    

    更简单、更安全,内存泄漏风险为零。

        2
  •  2
  •   Swift - Friday Pie    9 年前

    来自Qt文档

    现有的内存缓冲区,数据。宽度和高度必须为 以像素为单位指定,数据必须32位对齐,并且 图像中的数据也必须是32位对齐的。

    缓冲区必须在QImage的整个生命周期内保持有效。这个 图像在销毁时不会删除缓冲区。

    您需要实现自己的方法来删除该缓冲区

        3
  •  2
  •   Jeremy Friesner    9 年前

    所以你需要删除 data 当然,技巧是不要太快删除它——特别是,当QImage对象可能还在使用它时,您不想删除它。在您的情况下,确保这一点的最简单方法是仅在QImage对象被销毁后删除它:

    void updateDisplay() {
       uchar *data = new ...; // array of pixel data
       ...
       {
          QImage image = QImage(data, width, height,
                          width, QImage::Format_Indexed8);
    
          pixmapItem->setPixmap(QPixmap::fromImage(image));
       }
       delete [] data;
    }
    

    (注意使用大括号创建内部范围,从而确保QImage对象从堆栈中弹出并销毁 之前 这个 delete [] data 行执行!)

    当然,一种更简单、更安全的方法是避免“何时删除”的问题,首先不要手动分配数组。相反,让QImage对象分配自己的数据数组,然后直接写入该数组:

    QImage image(width, height, QImage::Format_Indexed8);
    char * data = image.bits();
    // write into (data) here if you want to, but don't delete [] data, ever!  
    // instead, the QImage destructor will do any necessary deletes for you
    
        4
  •  2
  •   Community Mohan Dere    9 年前

    您可以将 QImage 用你自己的析构函数进行清理。

    class NativeBufferQImage : public QImage {
        uchar *data;
    
        // other stuff
    
    public:
        ~NativeBufferQImage() {
            delete[] this->data; 
        }
    };
    

    还请注意,自 奇玛格 源自 QPaintDevice 和 喷漆装置 有 virtual destructor 如果有人 delete 你的 NativeBufferQImage 通过指向其基类的指针(即。 奇玛格 ),您的析构函数也将被调用。

        5
  •  1
  •   Kuba hasn't forgotten Monica    9 年前

    最好的方法是不要这样做:

    void updateDisplay() {
        QImage image(width, height, QImage::Format_Indexed8);
        auto const data = image.bits();
        // you can modify the data here
        pixmapItem->setPixmap(QPixmap::fromImage(image));
    }