[Development] unique_ptr and Qt, Take 2

Daniel Teske qt at squorn.de
Fri May 3 19:22:20 CEST 2019


Hi,

a year back I wrote a patch that added unique_ptr apis to most of 
qtbase. I still think that would be a good addition to Qt, and thus I've 
updated the patch with the feedback gained at the Contributor Summit 
last year and taking into account that with Qt6, binary compatibility is 
not required. The result is: https://codereview.qt-project.org/#/c/260618/

Since not everyone remembers last years mail, I'll explain the problem 
that patch is trying to solve, but won't go into all the details:
Consider this small program:

QWidget widget;
QHBoxLayout *layout = new QHBoxLayout(&widget);
QPushButton *leftButton = new QPushButton("LEFT", &widget); // Owned by 
widget
layout->addWidget(leftButton); // No Ownership transfer

QPushButton* rightButton = new QPushButton("RIGHT"); // No owner
layout->addWidget(rightButton);   // Ownership transfer

QObject::connect(leftButton, &QPushButton::clicked,
         [leftButton]{
     QMenu menu;
     auto act = new QAction("Action!"); // No Owner
     menu.addAction(act); // No Ownership transfer
menu.exec(leftButton->mapToGlobal(leftButton->rect().bottomLeft()));
});
widget.show();

In that program:

* The left button is owned at construction by the parent.
* The right button is created unowned, but adding a widget to a layout 
automatically sets the parent
* The action is created unowned, and is leaked because addAction does 
not set the parent.

That is, even though:

* layout->addWidget(new QPushButton()) and
* menu->addAction(new QAction())

look very similar, the later leaks memory.

That's a less than ideal api. With Qt6 there's a opportunity to leverage 
unique_ptr to ensure that memory is not leaked.

The patch adds two ways to create new QObjects:

* std::make_unique<QPushButton>("LEFT"); and
* parent->makeChild<QPushButton>("RIGHT");
* adds various overloads for ownership transfer

The first half of the program would thus look like:

QWidget widget;
QHBoxLayout *layout = widget.makeChild<QHBoxLayout>();

QPushButton *leftButton = widget.makeChild<QPushButton>("LEFT");
layout->addWidget(leftButton);

std::unique_ptr<QPushButton> rightButton = 
std::make_unique<QPushButton>("RIGHT");
layout->addWidget(std::move(rightButton));

For second half, the naive transformation:

{
     QMenu menu;
     auto act = std::make_unique<QAction>("Action!");
     menu.addAction(act.get());
menu.exec(leftButton->mapToGlobal(leftButton->rect().bottomLeft()));
}

does no longer leak memory, instead the action is freed at the end of 
the scope as its still owned by the unique_ptr.

I believe that Qt6 is a unique opportunity to add apis for better memory 
management to Qt.

So, who thinks that this is something that ought to be a Qt6 feature?

And who wants to actually help make that happen?

daniel

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/development/attachments/20190503/99e19965/attachment.html>


More information about the Development mailing list