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 :

Utilisation de range-for sur un vector<unique_ptr>


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut Utilisation de range-for sur un vector<unique_ptr>
    Bonjour à tous

    Je me posais la question de savoir s'il était possible d'utiliser les range-based loop for sur un vecteur d'unique_ptr :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    void foo(A const& a) const {}
     
    typedef std::vector< std::unique_ptr<A> > V
    typedef V::const_iterator iterator;
     
    V v;
     
    // for(auto a : v) // error : le constructeur  par copie n'est pas valide
    //    foo(a);
     
    for (auto it = v.begin(); it != v.end(); ++it)
        transform(*it->get()); // ok avec un for normal
     
    std::for_each(v.begin(), v.end(), [](iterator it){ foo(*it->get()); } ); // ok avec les lambdas
    Remarque :
    - v a la responsabilité de la destruction des éléments du vecteurs : unique_ptr
    - foo() utilise simplement les éléments du vecteur : référence constante

    Si quelqu'un a une idée. Merci

    PS : il est possible d'utiliser "auto" dans la fonction lambda à la place de "iterator" ici ?
    PS2 : au cas où, gcc 4.6.1 sous Linux 64

    PS3 : encore sur l'utilisation de unique_ptr
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // Version 1
    auto a = new A;
    // traitements sur a
    v.push_back(std::unique_ptr<A>(a));
    m.insert(std::make_pair(k, a)); // m est de type map<K,A*>
     
    // Version 2
    auto a = std::unique_ptr<A>(new A);
    // traitements sur 
    m.insert(std::make_pair(k, a.get())); // ok
    v.push_back(std::move(a));
    m.insert(std::make_pair(k, a.get())); // fail...
    Quel est le plus sûr en terme de fuite mémoire ? en terme d'écriture ? dans le cas où les traitements ne peuvent pas lancer d'exception ? dans le cas où les traitements peuvent lancer des exception ?

    De plus, a priori, il n'y a pas de fonction make_unique qui serait équivalent à make_shared. Un oubli ? Un choix volontaire ? J'ai besoin de voir un opticien ?

    Merci

  2. #2
    Membre Expert

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Par défaut
    Bonjour,

    Je me posais la question de savoir s'il était possible d'utiliser les range-based loop for sur un vecteur d'unique_ptr :
    Oui, bien sur !
    Les range-based ne sont de toute façon pas très magiques en C++11, si je traduis la norme alors le compilateur remplace :
    for ( for-range-declaration : expression ) statement
    par :
    for ( auto __begin = std::begin(expression),
    __end = std::end(expression);
    __begin != __end;
    ++__begin ) {
    for-range-declaration = *__begin;
    statement
    }
    (Bon ok, j'avoue avoir passé sous silence deux trois subtilités lié à l'ADL mais tout se passe comme cela)
    Par example, avec le code suivant :
    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
     
    struct A
    {
       A(int value):value(value){}
       int value;
     
    };
     
    void foo(const A& a)
    {
       std::cout << a.value << "\n";
    }
     
    int main()
    {
       typedef std::vector<std::unique_ptr<A>> Vec;
        Vec vec;
     
       vec.push_back(std::unique_ptr<A>(new A(1)));
       vec.push_back(std::unique_ptr<A>(new A(2)));
       vec.push_back(std::unique_ptr<A>(new A(3)));
     
      //...
    Dans ce cas on a :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
       for(std::unique_ptr<A> i : vec)
       {
           foo(*i);
       }
    qui est remplacé par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
       for(Vec::iterator b = std::begin(vec), e = std::end(vec); e != b ; ++b) 
       {
          std::unique_ptr<A> uptr = *b;
          foo(*uptr);
       }
    }
    Clairement, ça ne peut pas marcher. On ne peut pas assigner un unique_ptr à un autre unique_ptr vu que tout l’intérêt d'un unique_ptr est d'être... unique

    Par contre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
       for(std::unique_ptr<A>& i : vec)
       {
           foo(*i);
       }
    donnera :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
       for(Vec::iterator b = std::begin(vec), e = std::end(vec); e != b ; ++b) 
       {
          std::unique_ptr<A>& uptr = *b;
          foo(*uptr);
       }
    Et la c'est OK.

  3. #3
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut

    Je suis très bête parfois... je n'avais même pas penser à utiliser une référence dans le for.


  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Le choix de la variable i n'est peut-être pas très heureux, même si on a l'habitude de l'utiliser dans les for. Mais parce qu'il signifie "integer" (même si après on passe à j, k...).

    Je mettrai plutôt quelque chose du genre : currentElement

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Utiliser un fichier XML sur un serveur FTP
    Par ired dans le forum Bases de données
    Réponses: 1
    Dernier message: 06/04/2005, 13h43
  2. std::sort() sur std::vector()
    Par tut dans le forum SL & STL
    Réponses: 20
    Dernier message: 05/01/2005, 19h15
  3. Utilisation de l'ASP sur un serveur Apache
    Par 3adoula dans le forum Réseau
    Réponses: 1
    Dernier message: 29/10/2004, 14h34
  4. [debutant STL] question sur les vectors
    Par killerjeff dans le forum SL & STL
    Réponses: 13
    Dernier message: 19/08/2004, 17h32
  5. Utilisation d'une variable sur plusieurs unités
    Par Yamaneko dans le forum Langage
    Réponses: 2
    Dernier message: 05/06/2003, 11h23

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