2
votes

Code example:

auto fileMenu = std::make_unique<QMenu>(this->menuBar()->addMenu("First"));
fileMenu->addAction("AFirst");

auto x = this->menuBar()->addMenu("Second");
x->addAction("ASecond");

Results:

I have 2 menus in menubar, but in first menu - for some reason, there are NO actions. Second menu correctly has action.

I have tried different approaches, like, class-member pointers, and so on, but this is shortest possible example - QAction is missing, if QMenu is unique_ptr. Can anyone explain this for me? Parent window is QMainWindow, just in case.

System info: Win8.1 x64, Compiler is VS2013, Qt 5.4 x32.

1
Hmm. I expect using std::unique_ptr for this to lead to a double delete since Qt will delete the child when the parent goes out of scope.drescherjm
You shouldn't wrap the QMenu in a unique_ptr; it is already managed by the menu bar.Carlton
QAction is not wrapped, QMenu is wrapped here.Starl1ght
Sorry, corrected. I was looking at the other overload for addMenu in the documentation, the one that returns a QAction.Carlton
Did your std::unique_ptr fileMenu go out of scope? Perhaps your fileMenu is already freed however still connected to the parent and you are experiencing UB.drescherjm

1 Answers

4
votes

In this line:

auto fileMenu = std::make_unique<QMenu>(this->menuBar()->addMenu("First"));

fileMenu becomes a new QMenu object (using this constructor). It's quite the same as:

std::unique_ptr<QMenu> fileMenu(new QMenu(this->menuBar()->addMenu("First")));

Then, you add an QAction to this temporary, new menu.

In the second case:

auto x = this->menuBar()->addMenu("Second");
x->addAction("ASecond");

x become a pointer to existing menu. That's the difference.

Anyway, usually you shouldn't hold QObjects using std::unique_ptr. In Qt, there is a convention that you form a tree from QObjects by assigning parent to each of them. The parent deletes it's children recursively and you shouldn't manage them manually or you may cause double free in some specific cases.