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

Langage C++ Discussion :

Implémentation pointeur unique.


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    40
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Mai 2007
    Messages : 40
    Par défaut Implémentation pointeur unique.
    Bonjour,

    Je suis en train de me former sur l'utilisation du pointeur unique (unique_ptr).
    Ainsi, je voudrais implémenter ce type de smart pointeur dans un certain algorithme qui initialement utilise des pointeurs bruts classiques et fonctionne très bien.

    Mais je rencontre des problèmes dans l'utilisation du pointeur unique.

    Afin de ne pas embrouiller les lecteurs de mon message par un code compliqué, j'ai pu reproduire le problème actuel dans un petit programme que je vous présente ci-dessous avec ses commentaires.

    Ce programme fonctionne très bien tant que je mets en commentaire les lignes 49 et 52.
    Dans ces lignes j’essaye simplement de transférer le contenu d’une case de tableau (contenant un pointeur) dans un pointeur de la même nature.
    Cela fonctionne avec les pointeurs bruts, mais j’obtiens des erreurs de compilation avec le unique_ptr :.


    Merci par avance.

    Cordialement

    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
     
    void testuniqueptr(void)
     
    {
     
        #define TAILLEMAX 10000 // Taille maximale du tableau de pointeurs de float à allouer.
     
        int Taille,k;
        int Taillemax(TAILLEMAX);
        typedef float *ADDFLOAT; // ADDFLOAT représente donc un pointeur sur float.
     
        string message("Taille du vecteur de float :");
     
        while (oglirnombre(Taille, message)) {
     
            if (Taille<=0 || Taille>Taillemax) continue;
     
            // Allocation dynamique d'un tableau de N=Taille ADDFLOAT :
     
            unique_ptr<ADDFLOAT[]> panier(new ADDFLOAT[Taille]); // panier est donc un tableau de ADDFLOAT. Ainsi, pour chaque k, panier[k] sera un pointeur sur float.
     
            for (k=0; k<Taille; k++ ) {
     
                // 1. On teste l'affectation à nullptr de panier[k] :
     
                panier[k]=nullptr;
     
                // 2. On alloue dans point un float, donc point est du même type que panier[k] (c'est à dire un pointeur sur float) :
     
                unique_ptr<float> point(new float);
     
                // 3. On assigne une valeur (en l'occurrence k), à l'adresse pointée par point, histoire de présenter un résultat contrôlable :
     
                (*point)=(float)k;
     
                // 4. On assigne point qui est un pointeur(valide) sur float, à panier[k], lui même pointeur sur float . Tout se passe bien, y compris à l'exécution :
     
                panier[k]=point.get();
     
                // 5. Inversement, on essaye d'assigner la valeur de panier[k] (pointeur sur float) à point (également pointeur sur float). C'est ici que ça se gâte :
     
                // 5.1 - 1er version (sans get()) :ERREUR compilation: "no match for operator= in point = panier.std::unique_ptr<_Tp ..."
     
                point=panier[k];
     
     
                // 5.2 - 2eme version (avec get()) :ERREUR compilation: "error: request for member 'get' in panier.std::unique_ptr<_Tp [], ..."
     
                point=panier[k].get();
     
     
                // On affiche les contenus de tous ces pointeurs pour vérification. Tout est ok à l'exécution lorsque les instructions 5.1 et 5.2 sont désactivées :
     
                cout << "panier[" << k << "]= " << (*panier[k]) << " (*point)= " << *point << endl;
     
            }
     
        }
     
    }

  2. #2
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    Sans les numéros de ligne en dur, c'est mieux.

    J'ai regardé ton code, mais je ne comprends pas ce que tu veux faire. Il est cependant peu probable que tu ais besoin d'un std::unique_ptr<float*[]>. D'où la question, qu'est ce que tu veux faire ?

    Cependant, sans comprendre ce que tu fais, j'ai plutôt l'impression que c'est un std::vector<float> dont tu as besoin. Les meilleurs cas d'utilisation de std::unique_ptr que tu pourras trouver c'est, AMA, des std::vector<std::unique_ptr<Base>>Base est une classe de base d'une hiérarchie polymorphe.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    40
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Mai 2007
    Messages : 40
    Par défaut
    Merci pour ta réponse,

    En fait le code que je présente, ne fait rien de particulier et n'a aucune logique.
    Il permet simplement de reproduire en l'isolant un problème que je rencontre dans la 'modernisation' d'un ancien algorithme de tri par ventilations qui fonctionne avec des pointeurs bruts.
    L'idée était de passer à l'unique_ptr pour éviter de gérer les delete dans la gestion de l'alloc dynamique que je fait dans mon algorithme.

    A ce stade, Je voudrais simplement comprendre pourquoi l'affectation de panier[k] à point ne fonctionne pas en lignes 44 ou 49.
    Et j'ai effectivement besoin de réaliser cette instruction dans mon algorithme.

    Pour le moment je préfère encore garder un tableaux plutôt que gérer un vector pour conserver la même structure que mon ancien algo. Mais dans une deuxième phase j'y réfléchirai.

  4. #4
    Membre Expert Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Par défaut
    Citation Envoyé par jcmic Voir le message
    En fait le code que je présente, ne fait rien de particulier et n'a aucune logique.
    Il permet simplement de reproduire en l'isolant un problème que je rencontre dans la 'modernisation' d'un ancien algorithme de tri par ventilations qui fonctionne avec des pointeurs bruts.
    L'idée était de passer à l'unique_ptr pour éviter de gérer les delete dans la gestion de l'alloc dynamique que je fait dans mon algorithme.
    Utilise tout simplement un std::vector<float> (?)
    std::unique_ptr est souvent nécessaire pour avoir le bon comportement vis-à-vis des fonctions virtual. As-tu besoin de ça ?

    Citation Envoyé par jcmic Voir le message
    Pour le moment je préfère encore garder un tableaux plutôt que gérer un vector pour conserver la même structure que mon ancien algo. Mais dans une deuxième phase j'y réfléchirai.
    Tu peux / dois utiliser des std::vector. Si tu ne veux pas modifier l'algo maintenant, tu peux utiliser la fonction membre .data() pour récupérer un truc à la C.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    40
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Mai 2007
    Messages : 40
    Par défaut
    Non je n'utilise pas de fonction virtual dans cet algo.

    Je voulais utiliser un pointeur unique dans le but de ne pas gérer moi-même la désallocation mémoire (par une procédure adaptée à l'algorithme et qui utilise donc delete à la base ).
    Comme cette procédure de désallocation (à la main) est couteuse en temps sur des tableaux et listes de grandes tailles, dégradant ainsi les performances de mon tri, je voulais simplement comparer à ce qu'il se passerait si le système lui-même gérait cette désallocation.
    D'où l'idée du pointeur unique.

  6. #6
    Membre Expert Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Par défaut
    J'ai une trrès bonne nouvelle pour toi alors
    Le compilateur le fait pour toi en fait. Comme illustré dans cet exemple :
    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
    // g++ -Wall -Wextra -Wconversion -Wsign-conversion -std=c++11 -pedantic -fopenmp main.cpp -o main && ./main
    // g++ -Wall -Wextra -Wconversion -Wsign-conversion -std=c++98 -pedantic -fopenmp main.cpp -o main && ./main
    // g++ -Wall -Wextra -Wconversion -Wsign-conversion -std=c++98 -pedantic main.cpp -o main && valgrind ./main
     
    #include <iostream>
    #include <vector>
    #include <string>
     
     
    int main()
    {
    	// Bloc
    	{
    		std::vector<std::string> v;
    		v.push_back("Le");
    		v.push_back("destructeur");
    		v.push_back("des");
    		v.push_back("objets");
    		v.push_back("alloués");
    		v.push_back("sur");
    		v.push_back("la");
    		v.push_back("pile");
    		v.push_back("est");
    		v.push_back("appelé");
    		v.push_back("automatiquement");
    		v.push_back("par");
    		v.push_back("le");
    		v.push_back("compilateur");
    		v.push_back("à");
    		v.push_back("la");
    		v.push_back("fin");
    		v.push_back("du");
    		v.push_back("bloc");
    		v.push_back("=)");
     
    		for (std::size_t i = 0; i < v.size(); ++i)
    		{
    			std::cout << v[i] << " ";
    		}
    		std::cout << std::endl;
    	}
     
    	return 0;
    }
    Et voilà la sortie avec Valgrind :
    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
    $ g++ -Wall -Wextra -Wconversion -Wsign-conversion -std=c++98 -pedantic main.cpp -o main && valgrind ./main
    //==6127== Memcheck, a memory error detector
    //==6127== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
    //==6127== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
    //==6127== Command: ./main
    //==6127== 
    Le destructeur des objets alloués sur la pile est appelé automatiquement par le compilateur à la fin du bloc =) 
    //==6127== 
    //==6127== HEAP SUMMARY:
    //==6127==     in use at exit: 0 bytes in 0 blocks
    //==6127==   total heap usage: 26 allocs, 26 frees, 1,098 bytes allocated
    //==6127== 
    //==6127== All heap blocks were freed -- no leaks are possible
    //==6127== 
    //==6127== For counts of detected and suppressed errors, rerun with: -v
    //==6127== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

  7. #7
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    Tu pourrais présenter l'algo directement ? Un code minimal qui reproduit le problème, c'est bien, mais faut quand même qu'il rend compte un minimum de la situation.

    Pour les erreurs (que tu aurais pu écrire en entier d'ailleurs) :
    5.1. : panier[k] est un float*, tu ne peux pas l'affecter à un unique_ptr<float>.
    5.2. : Comme c'est un float* il n'a pas de fonction membre get.

    Vouloir automatiser la gestion de la mémoire c'est très bien, mais ce n'est pas systématiquement synonyme d'utiliser un unique_ptr. Utiliser un vector c'est aussi automatiser la gestion de la mémoire.

Discussions similaires

  1. [Turbo Pascal] Allocation et désallocation de pointeurs dans une fonction
    Par neird dans le forum Turbo Pascal
    Réponses: 13
    Dernier message: 17/11/2002, 20h14
  2. djgpp et pointeurs far -2
    Par elvivo dans le forum Autres éditeurs
    Réponses: 16
    Dernier message: 29/07/2002, 22h43
  3. djgpp et pointeurs far
    Par elvivo dans le forum C
    Réponses: 2
    Dernier message: 13/07/2002, 00h44
  4. Réponses: 2
    Dernier message: 06/07/2002, 12h36
  5. Implémentation des fonctions mathématiques
    Par mat.M dans le forum Mathématiques
    Réponses: 9
    Dernier message: 17/06/2002, 16h19

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