[Development] unique_ptr and Qt, Take 2

Daniel Teske qt at squorn.de
Wed May 8 01:39:33 CEST 2019


Am 06.05.2019 um 12:04 schrieb Lars Knoll:
>
>> On 6 May 2019, at 10:27, Konstantin Shegunov <kshegunov at gmail.com 
>> <mailto:kshegunov at gmail.com>> wrote:
>>
>> On Mon, May 6, 2019 at 10:42 AM Lars Knoll <lars.knoll at qt.io 
>> <mailto:lars.knoll at qt.io>> wrote:
>>
>>     Not sure whether it’s most projects, but there certainly are
>>     users doing it. And we’ve been using the pattern in our examples
>>     in some cases as well. But I can relate to Allan that creating
>>     widgets on the stack is bad style (as it conflicts with the way
>>     we memory manage them), and if I’d have a choice today, I would
>>     probably prefer to enforce them to be created on the heap by some
>>     means.
>>
>>
>> Fine, there seems to be somewhat of an argument in that regard. I'd 
>> raise the question then, what should be done for QObject derived 
>> classes, and I don't mean the ones that come from Qt (i.e. QFile, 
>> which Thiago mentioned), but the ones the user defines. In the end 
>> QObject is for us to derive from - get signals and slots and all 
>> those goodies. But then if one restricts QObject to be on the heap 
>> how do we treat the user classes? What I mean is - you can control 
>> how allocations happen in the library, say you provide custom 
>> new/delete for QObject and/or QWidget and restrict the stack 
>> (presumably through some trickery that disables the constructor), 
>> does this mean we are to force the user to write their own allocation 
>> operators for their classes? This doesn't really sound practical to 
>> say the least. Moreover there's really little reason (from the user's 
>> point of view) to have something in the heap if it can go on the 
>> stack. What do we do with QCoreApplicaiton, force the heap on it?
>
> It’s somewhat of a philosophical discussion now, as we are where we 
> are and users can and are creating QObject’s on the stack. I don’t 
> think we can change that now (even for Qt 6), and restricting it would 
> lead to rather ugly syntax in C++ (as the language doesn’t really help 
> enforcing something like this). So that means we’ll have to continue 
> to support it.
>
That's something that needs to be taken into account in any change in 
how memory management could work in Qt6. The patch I propose does not 
take that into account and is indeed almost entirely source compatible. 
(No changes in Qt Creator required, and two minor changes in tests.)

And the constructors/apis that are marked with QT_UNSAFE_API by default 
don't even emit any warning. The user can opt into those warnings.

One thing I forgot to mention, which is something I only have a mediocre 
solution for is, modal QDialogs (or any other top level widgets) on the 
stack. For those the parent pointer is both the owner and indicates to 
which parent the dialog is modal. In my opinion, the best solution is to 
disentangle this. E.g. introduce a new method ::setModalTo(QWidget *), 
which if used overwrites to which parent a dialog is modal. (That is by 
default a dialog is modal to its parent, unless something else is set 
via setModalTo). This means code that uses modal widgets on the stack 
would need some conversion work, but that's as far as I can see the best 
solution.

> The main benefits I see here that this scheme can co-exist with current
> code, i.e. code bases could slowly opt-in and migrate step by step, and
> it does not add the need to sprinkle user side code with the typical
> smart pointer line noise.
The same is true for what I'm proposing. It can and does allow users to 
convert at they choosing, and since the vast majority of QObjects are 
created with parents, most QObjects will be created via makeChild. Using 
unique pointers is the exception not the norm with what I've proposed. 
And indeed due to the ergonomics of makeChild via make_unique, the user 
is steared towards using the better way to construct QObjects.

Now, what André is proposing is very similar to just having a owning 
smart pointer that remembers the pointed at object after it has lost 
ownership. I see no reason why that (or more fuller proxy classes) 
couldn't work. But,

* The class/smart pointer would need to be move only, which limits how 
useful it is.
* The semantics feel strange to me.

And while I'd encourage someone to try it out, I'm of the firm opinion 
that Qt should try to get over its NIH attitude. One of the issues with 
Qt in the real world is that it's just that tiny bit differently than 
what non Qt C++ users are familiar with for. Sometimes that's for a good 
reason. but there's a cost there that is imho unappreciated inside the 
Qt bubble.

Also nowadays C++ is changing quite fast and the way to profit from the 
advancements in standard c++ is by making sure that Qt works great with 
new standard c++ idioms. It's not by investing time into inventing a 
slightly different idiom.

For example, Microsoft is still researching whether static analysers 
could detect dangling pointers [2]. That tool obviously will understand 
unique_ptr and is unlikely to understand our custom solution.

daniel

[1] 
https://codereview.qt-project.org/#/c/260618/1/tests/auto/opengl/qglbuffer/tst_qglbuffer.cpp
  and 
https://codereview.qt-project.org/#/c/260618/1/tests/auto/opengl/qglbuffer/tst_qglbuffer.cpp

[2] 
https://devblogs.microsoft.com/cppblog/lifetime-profile-update-in-visual-studio-2019-preview-2/

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/development/attachments/20190508/39b3fc13/attachment.html>


More information about the Development mailing list