71 votes

Pourquoi les exemples officiels et les tutoriels Qt n'utilisent-ils pas les pointeurs intelligents?

Pourquoi ne officiel des exemples et des tutoriels à propos de la bibliothèque Qt, ne pas utiliser des pointeurs intelligents? Je ne vois qu' new et delete pour créer et détruire les widgets.

J'ai cherché la justification, mais je ne pouvais pas le trouver, et je n'en vois pas moi-même, sauf si c'est pour des raisons historiques ou vers l'arrière compatibilité: tout le monde ne veut que le programme de résilier si un widget constructeur échoue, et la manipulation via les blocs try/catch est juste moche (même si elle est utilisée dans quelques endroits). Le fait que le parent de widgets peut prendre la propriété des enfants est également à seulement explique en partie la chose pour moi, que vous devez utiliser delete pour les parents à un certain niveau.

63voto

UmNyobe Points 9508

Parce que Qt s'appuie sur un parent-enfant et de gérer les Qobject ressources. Il suit le composite + de la Chaîne de responsabilité, qui est utilisé à partir de cas de gestion pour la gestion de la mémoire, le dessin, la manipulation de fichiers, etc...

En fait, en essayant d'utiliser un QObject dans un shared\pointeur unique est overengineering (99% du temps).

  1. Vous devez fournir une coutume deleter, qui fera appel deleteLater
  2. Votre qobject avec les parents ont déjà une référence dans l'objet parent. Si vous savez qu'un objet n'est pas divulgué tant que le parent existe pas. Lorsque vous avez besoin de se débarrasser de lui, vous pouvez appeler deleteLater directement.
  3. Votre QWidget sans parent ont déjà une référence dans l'objet Qapplication. Alors même que le point 2.

Cela dit, vous pouvez toujours utiliser RAII avec Qt. Par exemple QPointer se comporte comme une référence faible sur un QObject. Je voudrais utiliser QPointer<QWidget> plutôt que d' QWidget*.

remarque: pour ne pas paraître trop fanboy, deux mots : Qt + valgrind.

24voto

Ralph Tandetzky Points 5310

Pointeurs intelligents pour les enfants

Le pointeur intelligent classes std::unique_ptr et std::shared_ptr sont pour la gestion de la mémoire. Avoir un tel pointeur intelligent signifie, que vous propre le pointeur. Cependant, lors de la création d'un QObject ou un type dérivé avec un QObject parent, la propriété (de la responsabilité de nettoyer) est remis à la société mère QObject. Dans ce cas, la bibliothèque standard de pointeurs intelligents sont inutiles, voire dangereux, car ils peuvent potentiellement causer une double délétion. Oups!

Raw des pointeurs vers des orphelins

Toutefois, lorsqu'un QObject (ou de type dérivé) est créé sur le tas, sans un parent QObject , les choses sont très différentes. Dans ce cas, vous ne devriez pas simplement tenir un pointeur brut, mais un pointeur intelligent, de préférence un std::unique_ptr à l'objet. De cette façon, vous gagnez des ressources de la sécurité. Si plus tard vous avez la main de l'appartenance de l'objet à un parent QObject vous pouvez utiliser std::unique_ptr<T>::release(), comme suit:

auto obj = std::make_unique<MyObject>();
// ... do some stuff that might throw ...
QObject parentObject;
obj->setParent( &parentObject );
obj.release();

Si les choses que vous faites avant de donner à votre orphelin d'un parent déclenche une exception, alors vous avez une fuite de mémoire, si vous avez utilisé pointeur brut de tenir l'objet. Mais le code ci-dessus est de sauvegarder l'encontre d'une telle fuite.

Sur un plan plus général

Il n'est pas C++ moderne des conseils pour éviter les pointeurs tous ensemble, mais pour éviter de posséder raw pointeurs. Je pourrais en ajouter un autre, C++ moderne des conseils: Ne pas utiliser des pointeurs intelligents pour les objets qui sont détenus par une autre entité de programme.

13voto

Gill Bates Points 3884

Vous avez déjà répondu à votre propre question: except if it's for historic reasons/backward compatibility . Une bibliothèque aussi volumineuse que QT ne peut pas supposer que tous ceux qui l'utilisent disposent de compilateurs prenant en charge C ++ 11. new et delete sont garantis dans les normes antérieures.

Cependant, si vous avez le soutien nécessaire pour utiliser des pointeurs intelligents, je vous encourage à les utiliser par-dessus des pointeurs bruts.

10voto

PRIME Points 516

En plus de ce que @Jamey a dit:

Si vous design intelligemment, vous pouvez ne jamais avoir à utiliser un delete sur un widget. Disons que vous avez une fenêtre principale, et de la création d'une auto objet et l'exécution de cette fenêtre dans la boucle d'événements. Maintenant reste tous les éléments de ce widget peut être ajouté en tant que ses enfants. Et puisque vous êtes de les ajouter à cette MainWindow directement/indirectement l'enfant, lorsque vous fermez cette fenêtre principale, tout sera pris en charge automatiquement. Juste vous devez vous assurer que tous les objets dynamiques/widgets que vous avez créé sont des enfants/petits-enfants de la MainWindow. Donc aucun besoin d'une explicite supprimer..

5voto

g24l Points 1355
  • QObject a un parent et l'arbre comme la structure de l' programme permet de gérer la mémoire de manière assez efficace.

  • Le dynamisme dans Qt sauts de nice idéal, par exemple, le passage d'un pointeur brut autour de. On peut facilement se retrouver en tenant un dangling pointer , mais qui est un problème commun dans la programmation.

  • L'intervalle Qt pointeur intelligent , en fait une référence faible, est - QPointer<T>
    et fournit une partie de la STL de bonbons.

  • On peut aussi mélanger avec std::unique_ptr et autres , mais il devrait être utilisé uniquement à des fins non-Qt machines dans votre programme.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X