IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

[template] un smart pointer parmi d'autres


Sujet :

C++

  1. #1
    Membre éprouvé
    Inscrit en
    avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : avril 2005
    Messages : 1 110
    Points : 935
    Points
    935
    Par défaut [template] un smart pointer parmi d'autres
    Voici un code de "smart pointer" que je viens de trouver. Il me parait simple et assez universel.
    Détail amusant, un operator "virgule" est défini. C'est bien la première fois que je vois ça.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    template<class T>
    class auto_counter
    {
    	long f_cnt;
    	T *f_ptr;
    	long Keep() { return ++f_cnt; }
    	long Release() { return --f_cnt; }
    	auto_counter()
    		:f_cnt(1),f_ptr(0) {}
    	explicit auto_counter(T *ptr)
    		:f_cnt(1),f_ptr(ptr) {}
    	auto_counter(const auto_counter<T> & r)
    		:f_cnt(r.f_cnt),f_ptr(r.f_ptr) {}
    	auto_counter<T> & operator=(const auto_counter<T> & r)
    		{ f_cnt=r.f_cnt;f_ptr=r.f_ptr;return *this; }
    public:
    	T *Get()
    		{ return f_ptr; }
    	static auto_counter<T> *Init(T *ptr)
    		{ return new auto_counter<T>(ptr); }
    	static void Done(auto_counter<T> *p)
    	{
    		if (p && p->Release()==0)
    		{
    			delete p->f_ptr;
    			delete p;
    		}
    	}
    	static void Copy(auto_counter<T> **dpp,auto_counter<T> *sp)
    	{
    		if (!sp)
    		{
    			if (*dpp) Done(*dpp),*dpp=0;
    		}
    		else if (!*dpp)
    			(*dpp=sp)->Keep();
    		else if ((*dpp)->f_ptr!=sp->f_ptr)
    		{
    			Done(*dpp);
    			(*dpp=sp)->Keep();
    		}
    	}
    };
     
     
    template<class T>
    class smart_ptr
    {
    	auto_counter<T> *f_ac;
    public:
    	smart_ptr()
    		:f_ac(NULL) {}
    	explicit smart_ptr(T *ptr)
    		:f_ac(NULL) { f_ac=auto_counter<T>::Init(ptr); }
    	smart_ptr(const smart_ptr<T> & r)
    		:f_ac(NULL) { auto_counter<T>::Copy(&f_ac,r.f_ac); }
    	smart_ptr<T> & operator=(const smart_ptr<T> & r)
    		{ auto_counter<T>::Copy(&f_ac,r.f_ac); return *this; }
    	~smart_ptr()
    		{ auto_counter<T>::Done(f_ac); }
    	bool operator,(bool b) const
    		{ return f_ac!=0 && f_ac->Get()!=0 && bool(*f_ac->Get())==b; }
    	operator bool() const
    		{ return f_ac!=0 && f_ac->Get()!=0; }
    	T & operator*() const
    		{ return *f_ac->Get(); }
    	T *operator->() const
    		{ return f_ac->Get(); }
    	T *get() const
    		{ return f_ac->Get(); }
    };
    Qu'en pensez-vous ?
    Merci.

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    27 233
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : septembre 2005
    Messages : 27 233
    Points : 40 967
    Points
    40 967
    Par défaut
    Salut,
    1. Déjà, quand je vois un opérateur virgule, ça me parait tout de suite suspect.
    2. Ensuite, la fonction copy() bénéficierait d'un passage par référence plutôt que par pointeur
    3. Et surtout, elle libère le pointeur existant avant d'augmenter le compteur de références du nouveau: Pas bien! (implémenter l'opérateur= par copy-and-swap serait une meilleure idée).
    4. Ce n'est pas thread-safe, mais bon, on ne peut pas faire du thread-safe en C++ standard.
    5. Ce pointeur intelligent fait juste la taille d'un pointeur, mais il fait une double indirection. J'ai plutôt tendance, lors d'un comptage de références non-intrusif, à stocker les deux au même niveau (mais je suis passé par des classes intermédiaires, donc ce code plus simple est peut-être plus exception-safe de ce côté-là)
    6. Ce code ne prend pas en charge le cas d'une erreur mémoire lors du new: ptr ne sera pas libéré...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Membre éprouvé
    Inscrit en
    avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : avril 2005
    Messages : 1 110
    Points : 935
    Points
    935
    Par défaut
    Merci pour ta réaction. Elle est intéressante bien que les à-priori 1, 2 et 3 te décribilisent un peu.

    Je n'avais pas réalisé le 6. En effet il serait judicieux de lever l'insécurité de ce memory leak (quoiqu'improbable).

    Le 5 me perturbe aussi un peu. Mais le code est simple et clair, et en pratique je serais surpris si les performances étaient vraiment affectées par l'indirection supplémentaire. Les cas critiques mériteront une implémention plus spécifique.

    D'autres avis ?
    Merci.

  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    mai 2006
    Messages
    779
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : mai 2006
    Messages : 779
    Points : 1 172
    Points
    1 172
    Par défaut
    Citation Envoyé par camboui Voir le message
    Merci pour ta réaction. Elle est intéressante bien que les à-priori 1, 2 et 3 te décribilisent un peu.

    D'autres avis ?
    "Détail amusant, un operator "virgule" est défini. C'est bien la première fois que je vois ça."

    ça te décrédibilise aussi un peu non?

    plus sérieusement, tu reproches quelque chose à tr1::shared_ptr ?

  5. #5
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    27 233
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : septembre 2005
    Messages : 27 233
    Points : 40 967
    Points
    40 967
    Par défaut
    Le 3 n'est pas un à-priori, mais une véritable faille en cas d'auto-affectation (ou d'un truc plus bizarre, comme dépiler une pile chaînée qui utiliserait ce genre de pointeur.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  6. #6
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : juin 2005
    Messages : 8 575
    Points : 11 801
    Points
    11 801
    Par défaut
    Citation Envoyé par camboui Voir le message
    Détail amusant, un operator "virgule" est défini. C'est bien la première fois que
    Tu n'as donc jamais vu boost.assign

    Sinon, effectivement je te déconseille d'utiliser ce pointeur là, je te conseille plutôt de lui préférer tr1::shared_ptr ou encore boost.smart_pointer (il s'agit +- de la même chose) ou bien celui de Loki (http://loki-lib.sf.net/).

  7. #7
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    27 233
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : septembre 2005
    Messages : 27 233
    Points : 40 967
    Points
    40 967
    Par défaut
    Mais en fait, l'opérateur virgule, je ne vois même pas à quoi il est supposé servir, ni ce que cette redéfinition fait...

    En clair, la plupart des redéfinitions de l'opérateur virgule sont contre-intuitives pour moi, et celle-ci en particulier l'est...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  8. #8
    Membre éprouvé
    Inscrit en
    avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : avril 2005
    Messages : 1 110
    Points : 935
    Points
    935
    Par défaut
    Vouloir n'est pas pouvoir. Boost ne fait pas partie des choix proposés malheureusement. J'aurais dû le préciser dès le départ...

    A propos du 3, l'auto-affectation est bien sûr un soucis, mais elle me semble ici traitée par Copy().

    A propos de l'operator "virgule", il y en a un qui trouve ça suspect, et un autre qui sous entend que boost en use et abuse abondamment.
    Les avis sont manifestement contrastés
    Si je comprends bien son usage dans ici, il permet d'appeler l'operator bool de la classe T (qui doit donc le définir). Sans doute pour tester la "validité" d'une instance de T (?), par exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    smart_ptr<T> p(...);
    if (p,false) cout << "Object non utilisable" << endl;
    Ce code est trouvé en interne. Je suis preneur de tout autre code qui se resume à un simple fichier header à inclure. Les usines à gaz me seront refusées (je ne décide pas).

    Merci encore

  9. #9
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    27 233
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : septembre 2005
    Messages : 27 233
    Points : 40 967
    Points
    40 967
    Par défaut
    Citation Envoyé par camboui Voir le message
    A propos du 3, l'auto-affectation est bien sûr un soucis, mais elle me semble ici traité par Copy().
    Ah, en effet, Copy() évite l'auto-affectation pure. Mais je peux te donner un cas tordu contre lequel Copy() ne protège pas:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    class UneClasse
    {
    public:
    	smart_ptr< UneClasse > suiv;
    	int i;
    	UneClasse(int i) : i(i) {}
    };
     
    int main(void)
    {
    	smart_ptr< UneClasse > test(new UneClasse(1));
    	test->suiv = new UneClasse(2);
    	test = test->suiv; //Ici, 1 va être détruite, et détruire 2, avant que la nouvelle référence vers 2 soit créée.
    	return 0;
    }
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  10. #10
    Membre éprouvé
    Profil pro
    Inscrit en
    mai 2006
    Messages
    779
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : mai 2006
    Messages : 779
    Points : 1 172
    Points
    1 172
    Par défaut
    Citation Envoyé par camboui Voir le message
    Vouloir n'est pas pouvoir. Boost ne fait pas partie des choix proposés malheureusement. J'aurais dû le préciser dès le départ...
    oui c'est pour ça que je t'ai parlé de tr1:: qui est peut être inclus à ton compilateur sans que tu n'ais rien à faire.

  11. #11
    Membre éprouvé
    Inscrit en
    avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : avril 2005
    Messages : 1 110
    Points : 935
    Points
    935
    Par défaut
    Nikko,
    tr1:: est inclus dans Visual C++ 2008 je crois. Je suis sous VC++6.0 et/ou 2003 (7.1 je pense). Le passage vers VC++ 2008 (v9.0?) est une option possible.
    Se sera peut-être pour bientôt.
    Merci.

    Médinoc,
    Les déclarations récursives mettent en péril Copy(), c'est juste. Voici une correction. J'en ai profité pour adapter Init() afin de satisfaire le point 6.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    	static auto_counter<T> *Init(T *ptr)
    	{
    		std::auto_ptr<T> ap(ptr);
    		auto_counter<T> *r=new auto_counter<T>(ptr);
    		ap.release();
    		return r;
    	}
    	static void Copy(auto_counter<T> **dpp,auto_counter<T> *sp)
    	{
    		if (sp)
    			sp->Keep();
    		if (*dpp)
    			Done(*dpp);
    		*dpp=sp;
    	}
    Reste le point4. Je pense qu'il suffit de remplacer ++f_cnt et --f_cnt dans Keep() et Release() par InterlockedIncrement() et InterlockedDecrement() (sous Windows). Ou en faut-il plus ?

  12. #12
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    27 233
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : septembre 2005
    Messages : 27 233
    Points : 40 967
    Points
    40 967
    Par défaut
    Généralement, on n'a pas besoin de plus. Mais je suis trop paresseux pour regarder à nouveau ce code de près.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  13. #13
    Membre éprouvé
    Inscrit en
    avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : avril 2005
    Messages : 1 110
    Points : 935
    Points
    935
    Par défaut
    Ton exemple "récursif" m'a donnée l'idée d'un smart pointer utilisant une liste circulaire au lieu du classique comptage. Du coup, le point 5 est levé. Cerise sur le gateau, le code est encore plus simple, de quoi vérifier sa robustesse plus facilement.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    template<class T>
    class csmart_ptr
    {
    	csmart_ptr<T> *f_ap;
    	T *f_ptr;
    public:
    	csmart_ptr()
    		:f_ap(),f_ptr(0) {f_ap=this;}
    	explicit csmart_ptr(T *ptr)
    		:f_ap(),f_ptr(ptr) {f_ap=this;}
    	csmart_ptr(const csmart_ptr<T> & r)
    		:f_ap(r.f_ap),f_ptr(r.f_ptr) { ((csmart_ptr<T> *)&r)->f_ap=this; }
    	csmart_ptr<T> & operator=(const csmart_ptr<T> & r)
    	{
    		if (&r!=this)
    		{
    			csmart_ptr<T> t(*this);
    			this->~csmart_ptr();
    			f_ap=r.f_ap; f_ptr=r.f_ptr; ((csmart_ptr<T> *)&r)->f_ap=this;
    		}
    		return *this;
    	}
    	~csmart_ptr()
    	{
    		if (f_ap==this)
    			delete f_ptr;
    		else
    		{
    			for (csmart_ptr<T> *tmp_ap=f_ap; tmp_ap->f_ap!=this; tmp_ap=tmp_ap->f_ap)
    				;
    			tmp_ap->f_ap=f_ap;
    		}
    	}
    	operator bool() const
    		{ return f_ptr!=0; }
    	T & operator*() const
    		{ return *f_ptr; }
    	T *operator->() const
    		{ return f_ptr; }
    	T *get() const
    		{ return f_ptr; }
    };
    Voilà, c'était le résultat de mes songes d'un WE enneigé

  14. #14
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    août 2004
    Messages
    5 460
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : août 2004
    Messages : 5 460
    Points : 16 192
    Points
    16 192
    Par défaut
    Quelques remarques en vrac :

    Les smart pointers sont souvent passés par copie. Avoir un destructeur en O(n) me semble donc limite. Il faut voir ce que ça donne en pratique.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    	csmart_ptr(const csmart_ptr<T> & r)
    		:f_ap(r.f_ap),f_ptr(r.f_ptr) { ((csmart_ptr<T> *)&r)->f_ap=this; }
    Là, tu as un const_cast, autant le dire afin de clarifier le code. En l'occurrence, il me semblerait pas mal :
    - soit de passer la liste chaînée en mutable
    - soit de carrément avoir un constructeur par copie prenant une référence non constante.

    Le pointeur me semble rudimentaire.Il ne supporte pas par exemple les opération entre pointeurs sur types différents, mais liés.

    Le pointeur est peut-être un peu gros, deux pointeurs en mémoire.

    Le code n'est pas thread safe, de nos jours, c'est souvent gênant.

    Un pointeur à comptage de références sans pointeur weak associé me semble pas vraiment fini.

    Dans ton opérateur d'affectation : Tu crée un pointeur a priori inutile, tu appelle explicitement un destructeur, chose rarement saine (je préfèrerais une fonction release() appelée dans le destructeur et l'opérateur=.

    tr1:: est inclus dans Visual C++ 2008 je crois.
    Dans VC++2008 SP1 uniquement.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  15. #15
    Membre éprouvé
    Inscrit en
    avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : avril 2005
    Messages : 1 110
    Points : 935
    Points
    935
    Par défaut
    Rapidement revu et corrigé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    template<class T>
    class csmart_ptr
    {
    	T *f_ptr;
    	csmart_ptr<T> *f_ap;
    	void Attach(const csmart_ptr<T> & r)
    	{
    		f_ap=r.f_ap;
    		(csmart_ptr<T> *)(&r)->f_ap=this;
    	}
    	void Detach()
    	{
    		for (csmart_ptr<T> *tmp_ap=f_ap; tmp_ap->f_ap!=this; tmp_ap=tmp_ap->f_ap)
    			;
    		tmp_ap->f_ap=f_ap;
    	}
    public:
    	csmart_ptr()
    		:f_ptr(0) {f_ap=this;}
    	explicit csmart_ptr(T *ptr)
    		:f_ptr(ptr) {f_ap=this;}
    	csmart_ptr(const csmart_ptr<T> & r)
    		:f_ptr(r.f_ptr) { Attach(r); }
    	csmart_ptr<T> & operator=(const csmart_ptr<T> & r)
    	{
    		if (&r!=this)
    		{
    			csmart_ptr<T> t(*this); //keep this line !
    			Detach();
    			f_ptr=r.f_ptr;
    			Attach(r);
    		}
    		return *this;
    	}
    	~csmart_ptr()
    	{
    		if (f_ap==this)
    			delete f_ptr;
    		else
    			Detach();
    	}
    	operator bool() const
    		{ return f_ptr!=0; }
    	T & operator*() const
    		{ return *f_ptr; }
    	T *operator->() const
    		{ return f_ptr; }
    	T *get() const
    		{ return f_ptr; }
    };
    const_cast et/ou static_cast: pour une raison que j'ignore le compilateur n'en veut pas (toujours VC++6 pour l'instant). C'est un détail que je clarifierai plus tard.

    En quoi le pointeur est "plus gros" que celui de boost par exemple ?

    multithread: J'ai isolé le code à verrouiller dans Attach() et Detach(), le cas échéant. Le code est ainsi plus "propre", sans appel explicite au destructeur.

    "Un pointeur à comptage de références sans pointeur weak associé me semble pas vraiment fini."
    Je ne comprend pas de quoi tu parles, là.

    L'opération d'affectation (operator=): le pointeur temporaire "t" n'est pas inutile, il est même indispensable. C'est un des aspects de la partie "copy" du "copy-and-swap" dont parlait Médinoc. Le destructeur de "t" sera appelé pour supprimer f_ptr si nécessaire. Sans ça, c'est le memory leak garanti.

  16. #16
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    27 233
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : septembre 2005
    Messages : 27 233
    Points : 40 967
    Points
    40 967
    Par défaut
    Pourquoi ne pas faire un vrai swap ?
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  17. #17
    Membre éprouvé
    Inscrit en
    avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : avril 2005
    Messages : 1 110
    Points : 935
    Points
    935
    Par défaut
    Je veux bien moi.
    J'ai essayé de retourner l'operator= dans tous les sens, je n'arrive pas à faire "mieux" (en particulier se passer du test d'auto-affectation).

  18. #18
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    27 233
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : septembre 2005
    Messages : 27 233
    Points : 40 967
    Points
    40 967
    Par défaut
    Il faut dire que le coup de la liste chaînée complique pas mal les choses. J'ai du mal à voir ce qu'il faut swapper ou non, surtout que ta liste possède un chaînage simple...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  19. #19
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    août 2004
    Messages
    5 460
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : août 2004
    Messages : 5 460
    Points : 16 192
    Points
    16 192
    Par défaut
    Citation Envoyé par camboui Voir le message
    En quoi le pointeur est "plus gros" que celui de boost par exemple ?
    Il contient 2 pointeurs, là où celui de boost n'en contient qu'un, qui pointe vers une structure avec ref count et pointeur.
    Citation Envoyé par camboui Voir le message
    "Un pointeur à comptage de références sans pointeur weak associé me semble pas vraiment fini."
    Je ne comprend pas de quoi tu parles, là.
    Peut-être est-ce plus détaillé là : http://loic-joly.developpez.com/tuto...inters/#LIII-B
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  20. #20
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    27 233
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : septembre 2005
    Messages : 27 233
    Points : 40 967
    Points
    40 967
    Par défaut
    Donc, le pointeur intelligent de boost est plus proche de celui posté au début?
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

Discussions similaires

  1. Template, Smart Pointer et Valeur par défaut
    Par oxyde356 dans le forum Langage
    Réponses: 10
    Dernier message: 23/03/2011, 00h08
  2. Réponses: 23
    Dernier message: 05/01/2006, 21h15
  3. Smart Pointer
    Par Fry dans le forum C++
    Réponses: 5
    Dernier message: 04/10/2005, 00h13
  4. Utilisation des smart pointer
    Par 0xYg3n3 dans le forum MFC
    Réponses: 11
    Dernier message: 22/04/2005, 19h37
  5. templates et smart pointers
    Par delire8 dans le forum C++
    Réponses: 9
    Dernier message: 10/07/2003, 17h26

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo