QGraphicsItems只能在堆上创建

QGraphicsItems can only be created on the heap?

本文关键字:创建 QGraphicsItems      更新时间:2023-10-16

在QMainWindow的构造函数中。。。

在堆上创建一个新的圆圈并将其传递到场景中,圆圈出现,一切都在工作:

    QGraphicsScene * scene = new QGraphicsScene(this);
    CustomGraphicsView * view = new CustomGraphicsView(scene,this);
    QGraphicsEllipseItem * ellipse = new QGraphicsEllipseItem (100,100,30,30);
    ellipse->setPen(QPen(Qt::green,10));
    scene->addItem(ellipse);

现在我们在堆栈上创建一个圆,并通过引用传递它。但这一次,危机永远不会出现:

QGraphicsScene * scene = new QGraphicsScene(this);
CustomGraphicsView * view = new CustomGraphicsView(scene,this);
QGraphicsEllipseItem ellipse(100,100,30,30);
ellipse.setPen(QPen(Qt::green,10));
scene->addItem(&ellipse);

我想它在出现之前就被摧毁了。但我不明白为什么?为什么这不起作用?这种行为背后的规则是什么?

来源http://doc.qt.io/qt-4.8/qgraphicsscene.html#addItem

将项目及其所有子项添加或移动到此场景中。此场景取得项目的所有权。

如果某个项是在堆栈上创建的,则QGraphicsScene无法获得该项的所有权。这意味着必须在堆上创建项。

QGraphicsEllipseItem * ellipse = new QGraphicsEllipseItem (100,100,30,30);
ellipse->setPen(QPen(Qt::green,10));
scene->addItem(ellipse);

这是因为scene对象负责通过new分配的对象的delete。在Qt框架的深处,会有一个类似于的调用

delete item;

现在有了这个代码:

QGraphicsEllipseItem ellipse(100,100,30,30);
ellipse.setPen(QPen(Qt::green,10));
scene->addItem(&ellipse);

想想会发生什么。delete item;仍然存在,但它不仅将应用于指向本地对象的指针,而且(可能,取决于程序流程)还将应用于不再存在的对象的指针。执行delete的代码根本不知道对象是通过new创建的而不是

任何多次破坏对象的尝试都是未定义的行为,就像试图使用已被破坏的对象一样。你的问题是一个很好的例子,说明了为什么传递指向本地对象的指针应该被视为一种特别危险的操作,需要格外小心。

顺便说一下:

但这一次,危机永远不会出现:

这纯属巧合。未定义的行为意味着一切都有可能发生。