Partage
  • Partager sur Facebook
  • Partager sur Twitter

unique_ptr

C++

Sujet résolu
16 février 2019 à 9:03:10

Bonjour OC,

Je reviens sur unique_ptr plus spécifiquement.

Mr Scott Meyers dit :

..."Lorsque cela se produit, la donnée membre std::unique_ptr de l'objet est également détruite, ce qui déclenche la libération de la ressource renvoyée par la fabrique. Si la chaîne de propriété est interrompue en raison d'une exception ou d'un autre flux de contrôle inhabituel (par exemple le retour précoce d'une fonction ou un break dans uns boucle) , le destructeur du std::unique_ptr qui détient la ressource générée finira par être invoquée, avec pour conséquence la destruction de cette ressource".

J'ai 3 questions sur ce passage :

1) Pouvez-vous m'expliquer avec une situation concrète ce que signifie l'expression "Si la chaîne de propriété est interrompue" ?

2) Lorsque Mr Scott Meyers dit que

"le destructeur du std::unique_ptr qui détient la ressource générée finira par être invoquée, avec pour conséquence la destruction de cette ressource"

est-ce parce que l'objet de class std::unique_ptr est un objet qui est alloué automatiquement (et non pas dynamiquement) et que du coup, ce sont les règles pour les variables locales qui s'appliquent ?

3) Si c'est cela, la destruction a-t-elle lieu au moment du break ou du retour précoce de la fonction ?

Merci par avance

CREDIT : "Programmez efficacement en C++, de Scott Meyers (Dunod). Copyright 2016 Dunod pour la version française 978-2-10-074391-9, et 2015 Scott Meyers pour la versio d'origine 978-1-491-90399-5"

-
Edité par pseudo-simple 16 février 2019 à 14:21:58

  • Partager sur Facebook
  • Partager sur Twitter
16 février 2019 à 10:12:37

As tu lu le code source de unique_ptr ? C'est le top pour bien comprendre comment ca marche ! https://github.com/llvm-mirror/libcxx/blob/master/include/memory#L2400
  • Partager sur Facebook
  • Partager sur Twitter
16 février 2019 à 10:37:30

Bonjour gbidivers, c'est assez long comme code.

J'essaie quand même de comprendre.

Pouvez-vous me guider un peu ?

C'est quoi les mots :

_LIBCPP_TEMPLATE_VIS

_LIBCPP_INLINE_VISIBILITY



à quoi sert la ligne : #ifndef _LIBCPP_CXX03_LANG ?

Comment ces mots sont -ils compris par le compilateur? ?

Merci

  • Partager sur Facebook
  • Partager sur Twitter
16 février 2019 à 10:41:46

Ce sont des constantes définies par #define. https://en.cppreference.com/w/cpp/preprocessor 

Et pour "#ifndef"... tu n'as pas reconnu la directive que tu utilises tout le temps dans tes codes pour faire des header guards ?

  • Partager sur Facebook
  • Partager sur Twitter
16 février 2019 à 11:42:41

Des header quoi ?

Si on en est là, je pense qu'il faut abandonner tout espoir de pouvoir l'aider un jour...

EDIT:

J'ai l'impression que tu ne fais que lire des trucs sur le C++.
Ca ne marche pas comme ça, tu ne comprendras jamais rien ainsi.

Si tu veux un bon conseil, prends un projet simple (Javaquarium, par exemple) et implémente le, en C++, tu comprendras beaucoup mieux.

-
Edité par dragonjoker 16 février 2019 à 11:47:30

  • Partager sur Facebook
  • Partager sur Twitter

Si vous ne trouvez plus rien, cherchez autre chose.

16 février 2019 à 12:22:30

Modéré par Benzouye : zut à la fin les gamineries

@GBDIVERS : c'est la première fois que je vois une ligne de préprocessing dans la déclaration d'une classe comme ça

class _LIBCPP_TEMPLATE_VIS unique_ptr

POurrais-tu m'indiquer une référence dans le livre de Mr Lippman pour savoir comment ça marche ?

Car j'ai acheté le livre de Mr Lippman pour pouvoir suivre tes conseils

Merci par avance

-
Edité par Benzouye 16 février 2019 à 19:15:53

  • Partager sur Facebook
  • Partager sur Twitter
16 février 2019 à 12:41:49

Tu as juste un truc à faire : chercher la définition de ce _LIBCPP_TEMPLATE_VIS, dans les fichiers de ton compilo (parce que oui, ce n'est pas standard, et ne sera donc écrit dans aucun livre... J'ai au moins compris ça, de mon côté...).
Tu prends ton IDE, tu cherches la définition du symbole, et c'est réglé. C'est dur de se sortir les doigts du ... hein ?

Et ensuite, tu prends ce code, et tu le jettes, parce que tu n'en as pas besoin.

Expérimente, tu ne l'as pas fait, et ça transpire dans tes propos.
Et quand je parle d'expérimenter, ce n'est pas prendre des bouts de code à droite à gauche, pour les compiler sans comprendre.
Ce que je veux dire, c'est : crée un projet (me dis pas que tu apprends le C++ juste pour une ligne dans ton CV, rassure moi ?) et bosse dessus, c'est comme ça que tu apprendras. Pas en posant des questions sur des concepts qui sont bien au-delà de ton niveau.

  • Partager sur Facebook
  • Partager sur Twitter

Si vous ne trouvez plus rien, cherchez autre chose.

16 février 2019 à 13:15:32 - Message modéré pour le motif suivant : Non respect des règles du forum


16 février 2019 à 13:52:58 - Message modéré pour le motif suivant : Non respect des règles du forum


Si vous ne trouvez plus rien, cherchez autre chose.

16 février 2019 à 13:56:53 - Message modéré pour le motif suivant : Non respect des règles du forum


Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

16 février 2019 à 13:56:59

Troll : En argot Internet, un troll caractérise ce qui vise à générer des polémiques. Il peut s'agir d'un message (par exemple sur un forum), d'un débat conflictuel dans son ensemble ou de la personne qui en est à l'origine. Ainsi, « troller », c'est créer artificiellement une controverse qui focalise l'attention aux dépens des échanges et de l'équilibre habituel de la communauté.

Les impacts négatifs du trolling sur les communautés :

  • création d'un environnement hostile
  • détournement des activités des communautés (leurs échanges vont se concentrer sur le troll plutôt que sur le sujet initial qui les réunissait)
  • polarisation des opinions et croyances

source : https://fr.wikipedia.org/wiki/Troll_(Internet)

Je ne dis pas que tu en es un @Yes, man... Mais cela y ressemble fortement. Puis, quand on voit à quel point tu n'écoutes pas les intervenants qui prennent de leur temps pour te répondre (dans le vide bien souvent), mieux vaut prendre un bon paquet de pop corn et profiter du spectacle plutôt que de participer à celui-ci.

Je vois 2 cas possibles pour ta personne :

  • Tu es un troller de génie (dans ce cas respect parce que depuis le temps...)
  • Tu es d'une étroitesse d'esprit déconcertante (dans ce cas, il serait peut-être bon de remettre en question tes relations sociales avec le monde extérieur qui ne te veux pas de mal, puisque bien souvent tu sembles penser le contraire et bien évidemment accepter la critique et la remise en question)

Mais bon j'ai beau dire tout ça, je sais pertinnement que je parle dans le vide (ou bien je nourris un troll).

À bon entendeur, bon week-end :).

-
Edité par Guit0Xx 16 février 2019 à 14:00:40

  • Partager sur Facebook
  • Partager sur Twitter

...

16 février 2019 à 14:03:53

Merci à GuitOxx qui semble plus modéré dans ses propos en tout cas

Je reviens à mon sujet C++ maintenant que ces abus sont terminés.

J'avoue que je suis un peu perdu dans ce code assez long du lien envoyé par gbdivers

Auriez-vous une référence dans le livre de Mr Lippman qui me permette de comprendre mieux le code du lien envoyé par gbdivers car il y a des classes template partout et je voudrais comprendre le fil conducteur qui a permis de coder cette classe  unique_ptr ?

Merci

-
Edité par pseudo-simple 16 février 2019 à 14:15:08

  • Partager sur Facebook
  • Partager sur Twitter
16 février 2019 à 14:12:20

@gbdivers: c'est une implémentation tout à fait discutable ;) , oui oui va ramer sur du code non "OC friendly", c'est vraiment méchant :(

A la place je propose plutôt cet excellent pdf... Là exit les médisants, les rageux d'OC, on est dans la vraie science c++, "dans le dur" comme on dit, pas de raillerie, pas de compromis, immersion directe dans le grand bain au milieu des requins* ^^

(*) L'aspirine n'est pas fournie, penser à approvisionner quelques dizaines de tonnes ^^

-
Edité par int21h 16 février 2019 à 14:24:23

  • Partager sur Facebook
  • Partager sur Twitter
Mettre à jour le MinGW Gcc sur Code::Blocks. Du code qui n'existe pas ne contient pas de bug
16 février 2019 à 14:18:05

Bon là, j'avoue tu m'as fait rire avec ce pavé de 1729 pages  ;) @int21h

Peux-tu revenir à mon message initial stp  ?

Mr Scott Meyers dit :

..."Lorsque cela se produit, la donnée membre std::unique_ptr de l'objet est également détruite, ce qui déclenche la libération de la ressource renvoyée par la fabrique. Si la chaîne de propriété est interrompue en raison d'une exception ou d'un autre flux de contrôle inhabituel (par exemple le retour précoce d'une fonction ou un break dans uns boucle) , le destructeur du std::unique_ptr qui détient la ressource générée finira par être invoquée, avec pour conséquence la destruction de cette ressource".

J'ai 3 questions sur ce passage :

1) Pouvez-vous m'expliquer avec une situation concrète ce que signifie l'expression "Si la chaîne de propriété est interrompue" ?

2) Lorsque Mr Scott Meyers dit que

"le destructeur du std::unique_ptr qui détient la ressource générée finira par être invoquée, avec pour conséquence la destruction de cette ressource"

est-ce parce que l'objet de class std::unique_ptr est un objet qui est alloué automatiquement (et non pas dynamiquement) et que du coup, ce sont les règles pour les variables locales qui s'appliquent ?

3) Si c'est cela, la destruction a-t-elle lieu au moment du break ou du retour précoce de la fonction ?

Merci par avance

CREDIT : "Programmez efficacement en C++, de Scott Meyers (Dunod). Copyright 2016 Dunod pour la version française 978-2-10-074391-9, et 2015 Scott Meyers pour la versio d'origine 978-1-491-90399-5"

-
Edité par pseudo-simple 16 février 2019 à 14:21:09

  • Partager sur Facebook
  • Partager sur Twitter
16 février 2019 à 14:27:20

Tout est dans le bloc de béton de 1729 pages...

-
Edité par int21h 16 février 2019 à 14:27:58

  • Partager sur Facebook
  • Partager sur Twitter
Mettre à jour le MinGW Gcc sur Code::Blocks. Du code qui n'existe pas ne contient pas de bug
16 février 2019 à 14:33:19

Quelqu'un peut-il m'aider en prenant en compte les 3 questions,  sans envoyer un bloc de 1729 pages ?

Je vous remercie par avance

-
Edité par pseudo-simple 16 février 2019 à 14:41:37

  • Partager sur Facebook
  • Partager sur Twitter
16 février 2019 à 14:45:28

Si tu ne fais pas d'effort, pour éplucher le standard, on ne peut rien faire pour toi.
  • Partager sur Facebook
  • Partager sur Twitter

Si vous ne trouvez plus rien, cherchez autre chose.

16 février 2019 à 14:49:27

Tout bon développeur est passé par là. Éprouvant mais très formateur. :)
  • Partager sur Facebook
  • Partager sur Twitter
16 février 2019 à 15:14:15

Merci Maluna34 pour ton ton encourageant. J'apprécie ce genre de message.

Allez, de mon côté, j'y mets aussi du mien :

Sauriez-vous si le document du standard envoyé par int21h existe au format livre ?

Car c'est plus facile pour moi d'avoir lun livre de 1729 pages sous la main que en pdf sur écran.

Je n'ai pas trouvé sur amazon

Merci pour vos suggestions

EDIT : j'ai commencé à regarder le standard de 1729 pages et c'est vrai qu'il y a des réponses à mes questions dedans concernant le détail de l'implémentation de unique_ptr

Une version papier serait top si vous la connaissez

-
Edité par pseudo-simple 16 février 2019 à 16:36:09

  • Partager sur Facebook
  • Partager sur Twitter
16 février 2019 à 16:48:19

Bien sur que tu peux acheter la version papier. Pas la version de 1729 pages, qui est le brouillon de travail en cours, mais celle de 1605 pages, qui correspond au C++17 officiel : https://www.iso.org/standard/68564.html 

Il faut savoir que les pointeurs intelligents du C++11 sont en fait les pointeurs intelligents de boost. C'est donc intéressant de lire également la doc de boost correspondante : https://www.boost.org/doc/libs/1_69_0/libs/smart_ptr/doc/html/smart_ptr.html 

Et bien sur, comme expliqué dans la doc de boost, les pointeurs intelligents ne sont qu'une mise en application du concept RAII ("resource acquisition is initialization"), qui a été expliqué par Stroustrup dans son livre "The C++ Programming Language". Il faut absolulement le lire aussi ! https://www.amazon.com/C-Programming-Language-4th/dp/0321563840 

-
Edité par gbdivers 16 février 2019 à 17:06:58

  • Partager sur Facebook
  • Partager sur Twitter
16 février 2019 à 23:23:25

Bonsoir,

Dans le passage que j'ai cité, il y a un passage que je ne suis pas certain de comprendre malgré les compléments apportés par le standard : Pouvez-vous m'expliquer par quel mécanisme "le destructeur du std::unique_ptr qui détient la ressource générée finira par être invoquée" ?   

"Si la chaîne de propriété est interrompue en raison d'une exception ou d'un autre flux de contrôle inhabituel (par exemple le retour précoce d'une fonction ou un break dans uns boucle) , le destructeur du std::unique_ptr qui détient la ressource générée finira par être invoquée

Pouvez-vous m'expliquer par quel mécanisme "le destructeur du std::unique_ptr qui détient la ressource générée finira par être invoquée" ?

car si on sort précocément de la fonction ou qu'il y a un break, est-ce simplement parce que un unique_ptr suit les règles de l'allocation automatique et que par conséquent même en sortie prématurée, c'est la désallocation automatique qui s'applique à un unique_ptr ?

Par avance merci 

-
Edité par pseudo-simple 16 février 2019 à 23:25:21

  • Partager sur Facebook
  • Partager sur Twitter
16 février 2019 à 23:25:04

C'est le concept du RAII. Lis le livre de Stroustrup.
  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
16 février 2019 à 23:48:49

Le concept de RAII implique que le destructeur est toujours appelé (presque, je t'épargne les détails), donc qu'on met le mécanisme de libération dedans pour être sûr que tout est bien libéré.

Voici un lien vers un cours, pour que tu fasse pas ta mauvaise foi qui prétend qu'on le persécute. Même si en lisant un cours meilleurs que celui d'OC, que manifestement tu n'as pas lu non plus, tu connaîtrais déjà ce concept. :-°

https://zestedesavoir.com/tutoriels/460/simplifier-la-gestion-de-la-memoire-en-c-avec-raii/

  • Partager sur Facebook
  • Partager sur Twitter
17 février 2019 à 0:03:04

YES, man a écrit:

Pouvez-vous m'expliquer par quel mécanisme "le destructeur du std::unique_ptr qui détient la ressource générée finira par être invoquée" ?

car si on sort précocément de la fonction ou qu'il y a un break, est-ce simplement parce que un unique_ptr suit les règles de l'allocation automatique et que par conséquent même en sortie prématurée, c'est la désallocation automatique qui s'applique à un unique_ptr ?

Oui.
Quand on arrive à la fin de la zone d'utilisation d'un objet son destructeur est appelé. C'est à la fin du programme pour les variables globales, à la fin du thread pour les variables thread_local, à la fin du bloc pour les variables locales, au moment de l'appel à delete pour les variables allouées dynamiquement. Pour les sous objets contenus dans un autre, c'est au moment où leur contenant est détruit (à cause d'une des raisons précédentes). On peut aussi forcer un appel direct du destructeur mais même Scott Meyer ne le fait pas.
Dans tous les cas, le compilateur a bien placé l'appel du destructeur au bon endroit dans le code. Pour les variables locales, il sait aussi le placer en cas de break, de return ou d'exception. C'est ce que le traducteur à appelé "chaîne de propriété interrompue".
Quand le std::unique_ptr<> est détruit (suite à une des causes ci-dessus) son destructeur est donc appelé, et ce destructeur contient la demande de détruire (par un delete) l'objet pointé. Donc détruire le pointeur implique d'aussi détruire le pointé.
  • Partager sur Facebook
  • Partager sur Twitter

En recherche d'emploi.

17 février 2019 à 1:08:45

Merci Daflab pour cette explication précise.

En fait, d'après le standard, si j'ai bien compris, si on ne veut pas faire d'abus de langage :

quand on détruit le pointeur de type unique_ptr, on libère la ressource pointée par le pointeur nu , qui est lui-même stocké dans le unique_ptr si j'ai compris la documentation du standard.

EDIT : j'édite mon message car j'ai fait une recherche sur la notion des deleter dans le standard pour mieux comprendre la forme du deleter employé par Scott Meyers et comment cela s'articule avec le morceau de code de Mr Scott Meyers :

Si je comprends le fonctionnement du deleter personnalisé, le pointeur pInvestment en paramètre de la fonction lambda correspondra de manière exacte au pointeur nu (membre) contenu dans l'instance de type unique_ptr (pointeur nu qui lui-même pointe vers la ressource de type Investment stricto sensu) ?   (si l'on veut vraiment éviter les abus de langage) ?

auto delInvmt = [](Investment* pInvestment)
{
makeLogEntry(pInvestment);
delete pInvestment;

};

template<typename... Ts>
std::unique_ptr<Investment, decltype(delInvmet)>
makeInvestment(Ts&&... params)
{
std::unique_ptr<Investment, decltype(delInvmt)>
pInv(nullptr,delInvmt);


...
return pInv;
}



-
Edité par pseudo-simple 17 février 2019 à 18:34:23

  • Partager sur Facebook
  • Partager sur Twitter
17 février 2019 à 18:46:54

Josuttis explique super bien dans son livre comment personnaliser les comportements des classes de la lib standard. C'est vraiement un livre a lire ! https://www.amazon.com/Standard-Library-Tutorial-Reference-2nd/dp/0321623215
  • Partager sur Facebook
  • Partager sur Twitter
17 février 2019 à 19:50:53

Merci pour la proposition de livre.

Est-ce que tu pourrais me confirmer ce que j'ai mis en caractère gras ? 

Merci par avance

  • Partager sur Facebook
  • Partager sur Twitter
17 février 2019 à 20:17:24

Alors, voici :

pour faire le test, j'ai adapté le code de la doc, et je pense que la réponse est affirmative. Je 'ai vérifié avec get() qui renvoie un pointeur sur l'objet "owné" et j'ai affichier le ptr dans le destructeur personnalisé et les adresses indiquées coïncident :

#include <iostream>
#include <memory>

int main ()
{
    auto deleter = [](int* ptr){
        std::cout << "[deleter called]\n";
        std::cout<<ptr<<'\n';
        delete ptr;
    };

    std::unique_ptr<int,decltype(deleter)> uniq(new int, deleter);
    //std::cout<<uniq<<std::endl;
    std::cout<<"le résultat du get : "<<uniq.get()<<'\n';
    std::cout << (uniq ? "not empty\n" : "empty\n");
    uniq.reset();
    std::cout << (uniq ? "not empty\n" : "empty\n");
}



-
Edité par pseudo-simple 17 février 2019 à 20:20:57

  • Partager sur Facebook
  • Partager sur Twitter
17 février 2019 à 21:11:35

What a surprise !

Ca ne t'a pas semblé logique ? Vraiment ?
Tu t'es posé la question ? Vraiment ?

Tu vas une fois de plus dire que mon intervention ne sert à rien, mais si tu pêches à ce point niveau logique, je me demande s'il ne vaudrait pas mieux arrêter l'apprentissage du C++, parce qu'en être là au bout de 2 ans...
On ne peut pas blâmer le cours d'OC, le problème, c'est toi...

  • Partager sur Facebook
  • Partager sur Twitter

Si vous ne trouvez plus rien, cherchez autre chose.