Должны ли классы, производные не от QObject, "всегда" помещаться в стек?

Исходя из мира Symbian, я привык максимально использовать кучу, чтобы избежать нехватки стекового пространства, особенно при обработке дескрипторов. Производные классы CBase всегда динамически размещались в куче, так как в противном случае их переменные-члены оставались бы неинициализированными. Применимо ли такое же соглашение к классам, производным от QObject?

В Qt, кажется, принято помещать, например, QString в стек. Содержимое строки помещается в кучу, в то время как QString действует как контейнер в стеке, или все помещается в стек?

2 ответа

Решение

Как сказал sje397: идиоматично ставить QString и контейнеры в стеке, поскольку они неявно используются совместно. Их внутренности (указатель p dimpl идиома) создаются в куче. Также нет смысла создавать сам объект в куче. Просто возникают проблемы с управлением памятью, и вы теряете свойства копирования при записи при передаче указателей на строки / контейнеры.

QObjects с другой стороны, вы хотите создать в куче почти во всех случаях, так как в противном случае они будут сразу же уничтожены. Они не могут быть скопированы или назначены (ну, это можно применить для собственных подклассов, но QObject семантика нарушается), и обычно они должны выживать в теле метода, в котором они созданы. Исключение составляет QDialog, который часто создается в стеке, а затем QDialog::exec, который блокирует, пока диалог не будет закрыт. Но даже это строго говоря небезопасно, поскольку внешние события (вызовы RPC, фоновые операции) могут привести к удалению диалога его родителем (если сам родитель удален) до возврата exec. Тогда создание диалогового окна в стеке приведет к двойному удалению при размотке стека -> сбой.

QString и многие другие классы Qt используют неявный обмен данными. Это означает, что память обычно выделяется в куче.

Другие вопросы по тегам