[Development] unique_ptr and Qt, Take 2

"Lutor, Zoltán" zoltan.lutor at gmail.com
Fri May 3 20:24:57 CEST 2019


+1 from my side.

Explicit ownership declaration is the king. always - all other solutions are paid with sweat and blood. but mainly with blood... ;)

Zoltan

On Friday, May 3, 2019, Daniel Teske wrote:
> 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
> 
>


More information about the Development mailing list