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

Boost C++ Discussion :

initialisation de circular_buffer


Sujet :

Boost C++

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    15
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 15
    Par défaut initialisation de circular_buffer
    Bonjour à tous!

    Je veux initialiser un objet de type vector < circular_buffer < int > > pour stocker des données en provenance d'une carte d'acquisition. Chaque voie va dans un buffer circullaire, que je dépile ailleurs.

    Mon soucis c'est que je n'arrive pas à initialiser le circular_buffer avec la taille voulue (capacity() retourne toujours 0). Pourtant le même code avec vector < vector < int > > fonctionne très bien!

    Je n'ai rien trouvé dans la documentation de boost qui explique ce phénomène, par contre la sortie de gcc donne des warnings que je ne comprends pas.

    Voilà le code :
    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
    #include <iostream>
    #include <vector>
    #include <boost/circular_buffer.hpp>
     
    using namespace std;
     
     
    int main()
    {
      int nbRow = 3 , nbCol = 5;
      boost::circular_buffer <int> cb(nbCol);
      cout << "cb.capacity = " << cb.capacity() << "\n";
     
      vector < boost::circular_buffer <int> > mcb(nbRow, boost::circular_buffer <int> (nbCol));
      cout << "mcb.capacity(vec) = " << mcb.capacity() << "\n";
      cout << "mcb.capacity(cb) = " << mcb[0].capacity() << "\n";
     
      vector < vector <int> > array(nbRow, vector <int> (nbCol));
      cout << "array.capacity(row) = " << array.capacity() << "\n";
      cout << "array.capacity(col) = " << array[0].capacity() << "\n";
    }
    Et voilà la sortie de gcc :
    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
    make && ./simpletemplate
     
    g++ -c -pipe -O2 -march=i586 -mtune=i686 -fmessage-length=0 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector -O2 -g -Wall -W  -I/usr/share/qt4/mkspecs/default -I.-I. -I../../../boost/boost_1_36_0 -I. -o main.o main.cpp
    ../../../boost/boost_1_36_0/boost/circular_buffer/base.hpp: In instantiation of ‘boost::circular_buffer<int, std::allocator<int> >’:
    main.cpp:11:   instantiated from here
    ../../../boost/boost_1_36_0/boost/circular_buffer/base.hpp:379: warning: type qualifiers ignored on function return type
    ../../../boost/boost_1_36_0/boost/circular_buffer/base.hpp:417: warning: type qualifiers ignored on function return type
    ../../../boost/boost_1_36_0/boost/circular_buffer/base.hpp:471: warning: type qualifiers ignored on function return type
    ../../../boost/boost_1_36_0/boost/circular_buffer/base.hpp:489: warning: type qualifiers ignored on function return type
    g++  -o simpletemplate main.o
    cb.capacity = 5
    mcb.capacity(vec) = 3
    mcb.capacity(cb) = 0
    array.capacity(row) = 3
    array.capacity(col) = 5
    Evidemment je pourrais me contenter de ça et faire un set_capacity() sur chaque élément du vecteur, mais je trouve ça dommage, de créer des objets pour les redimensionner tout de suite après.

    En fait j'aurais deux questions :
    1) Ca veut dire quoi ces warnings?
    2) Quelqu'un peut-il m'expliquer pourquoi ce que je cherche à faire ne fonctionne pas?

    Merci d'avance!

  2. #2
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Construction d'un boost::circular_buffer:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
        explicit circular_buffer(capacity_type capacity, const allocator_type& alloc = allocator_type())
        : m_size(0), m_alloc(alloc) {
            initialize(capacity);
        }
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        void initialize(capacity_type capacity) {
            m_first = m_last = m_buff = allocate(capacity);
            m_end = m_buff + capacity;
        }
    Donc, là tu vois que m_size est positionné à 0 et que les buffers sont alloués pour capacity.

    Le copy constructeur de boost::circular_buffer est:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
        circular_buffer(const circular_buffer<T, Alloc>& cb)
        : m_size(cb.size()), m_alloc(cb.get_allocator()) {
            m_first = m_last = m_buff = allocate(cb.capacity());
            BOOST_TRY {
                m_end = cb_details::uninitialized_copy_with_alloc(cb.begin(), cb.end(), m_buff, m_alloc);
            } BOOST_CATCH(...) {
                deallocate(m_buff, cb.capacity());
                BOOST_RETHROW
            }
            BOOST_CATCH_END
        }
    et:
    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
     
    template<class InputIterator, class ForwardIterator, class Alloc>
    inline ForwardIterator uninitialized_copy_with_alloc(InputIterator first, InputIterator last, ForwardIterator dest,
        Alloc& alloc) {
        ForwardIterator next = dest;
        BOOST_TRY {
            for (; first != last; ++first, ++dest)
                alloc.construct(dest, *first);
        } BOOST_CATCH(...) {
            for (; next != dest; ++next)
                alloc.destroy(next);
            BOOST_RETHROW
        }
        BOOST_CATCH_END
        return dest;
    }
    Donc, là l'objet est construit avec la même capacité, puis les éléments sont copiés. Comme il n'y a aucun élément, aucune copie n'est faite et par conséquent end == m_buff.
    enfin:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    capacity_type capacity() const { return m_end - m_buff; }
    Donc capacity()==0!
    J'avoue que c'est un peu décontenançant. Je ne connais pas très bien boost::circular_buffer, mais je suis aussi un peu surpris qaue end ne soit pas positionner à m_buff + cb.capacity() dans le copy constructeur.
    Pour palier à ton problème:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::vector < boost::circular_buffer <int> > mcb(nbRow, boost::circular_buffer <int> (nbCol,0));
    A ce moment, on initialise les éléments avec une valeur par défaut (0), donc, on aura une copie d'élément et tout ira mieux.

    Pour les warning, j'ai repris ton exemple et compilé avec gcc/windows, et je ne les obtiens pas.


    P.S.: l'avantage de boost, c'est qu'on a le code, donc parfois il peut être intéressant de regarder la mécanique interne pour comprendre des comportements inattendus.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    15
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 15
    Par défaut
    D'accord, je comprends en partie ce qui se passe, même si le comportement du copy constructor m'apparaît plutôt louche. Il semble d'ailleurs que d'autres se soient fait piéger (cf http://article.gmane.org/gmane.comp....ircular_buffer) , ce qui me laisse penser que ce comportement est voulu. Mais alors du coup je me demande à quoi il peut bien servir?

    Le truc que je ne comprends pas, c'est que je n'ai pas appelé le copy constructor, et je ne vois pas comment il est appelé. Tu peux m'éclairer ?

    Pour l'initialisation, ça me va comme solution, je la garde, merci!

    Ensuite pour les warnings, ça viens de l'option -W de gcc, mais peut-être aussi de la version, parce que je ne les avais pas avant en v4.2.1. Là je suis en v4.3.1. Cela dit, même en lisant le code, je ne comprends toujours pas ce que ça veut dire.

  4. #4
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par popoms Voir le message
    D'accord, je comprends en partie ce qui se passe, même si le comportement du copy constructor m'apparaît plutôt louche. Il semble d'ailleurs que d'autres se soient fait piéger (cf http://article.gmane.org/gmane.comp....ircular_buffer) , ce qui me laisse penser que ce comportement est voulu. Mais alors du coup je me demande à quoi il peut bien servir?
    J'avoue que je suis aussi un peu dubitatif. J'aurais attendu à ce que m_end soit ajusté en fonction de la capacité du buffer alloué. Mais, je ne suis pas expert sur boost::circular_buffer, donc peut être quelqu'un a une réponse rationnelle...

    Citation Envoyé par popoms Voir le message
    Le truc que je ne comprends pas, c'est que je n'ai pas appelé le copy constructor, et je ne vois pas comment il est appelé. Tu peux m'éclairer ?
    Le copy constructor est appelé lorsque tu initialise ton vecteur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    vector < boost::circular_buffer <int> > mcb(nbRow, boost::circular_buffer <int> (nbCol));
    En gros, ici tu créé nbRow objet boost::circular_buffer <int> en copy-construction avec comme paramètre : boost::circular_buffer <int> (nbCol). Pour être plus clair, voici une pseudo-implémentation:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    vector < boost::circular_buffer <int> > ::vector < boost::circular_buffer <int> > (size_t NbrElement, boost::circular_buffer <int> Element0)
    {
         for(;NbrElement>0;--NbrElement){
               push_back(boost::circular_buffer <int>(Element0));// Appel du constructeur par copie
         }
    }
    Citation Envoyé par popoms Voir le message
    Ensuite pour les warnings, ça viens de l'option -W de gcc, mais peut-être aussi de la version, parce que je ne les avais pas avant en v4.2.1. Là je suis en v4.3.1. Cela dit, même en lisant le code, je ne comprends toujours pas ce que ça veut dire.
    Là, j'ai pas plus d'info. Mais, j'ai boost 1.35 et toi la 1.36. Peut être que la différence est là aussi?

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    15
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 15
    Par défaut
    Si je comprends bien le copy constructeur est appelé à chaque fois que j'initialise un vecteur, donc si je fais
    J'appelle 15 fois le copy constructeur du type (int), c'est ca ?


    Mais, j'ai boost 1.35 et toi la 1.36. Peut être que la différence est là aussi?
    En fait j'avais la 1.35, je suis passé en 1.36 pour voir si ça corrigeait. Donc je crois pas que ça vienne de là.

  6. #6
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    J'appelle 15 fois le copy constructeur du type (int), c'est ca ?
    Je dirais plutôt un appel au constructeur par défaut et 15 constructeurs de copie.

  7. #7
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par loufoque Voir le message
    Je dirais plutôt un appel au constructeur par défaut et 15 constructeurs de copie.
    Pour finir de chipoter, je dirais qu'il n'y a pas d'appel au constructeur par défaut. L'objet T0 d'initialisation est passé en paramètre dans la déclaration:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     vector < boost::circular_buffer <int> > mcb(nbRow, boost::circular_buffer <int> (nbCol));
    Et en l'occurence, il ne s'agit pas du constructeur par défaut...

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    15
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 15
    Par défaut
    OK, merci à tous les deux pour vos réponses ... éclairantes !


  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    15
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 15
    Par défaut
    J'en remet une petite couche pour avertir les autres utilisateurs de ce conteneur bien pratique, le comportement du copy constructeur est bien un bug, et non un comportement voulu comme je le croyais. Il sera corrigé pour la version 1.37, le patch est déjà dans le trunk et fonctionne sur mon exemple simple. Apparement la correction n'était pas triviale et a été repoussée au moins deux fois.

    Un code qui marche avec boost-trunk :
    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
    #include <iostream>
    #include <vector>
    #include <boost/circular_buffer.hpp>
     
    using namespace std;
     
    int main()
    {
      boost::circular_buffer<int> cb(3);
      vector<int> vec(3);
      cout << "cb.capacity = " << cb.capacity() << "\n";
      cout << "vec.capacity = " << vec.capacity() << "\n";
     
      boost::circular_buffer<int> cb2 = cb;
      vector<int> vec2 = vec;
      cout << "cb2.capacity = " << cb2.capacity() << "\n";
      cout << "vec2.capacity = " << vec2.capacity() << "\n";
    }
    La sortie est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    tom@destiny:~/boost_cb> ./boost_cb
    cb.capacity = 3
    vec.capacity = 3
    cb2.capacity = 3  // et non plus 0!!
    vec2.capacity = 3


    le trunk : svn co http://svn.boost.org/svn/boost/trunk boost-trunk
    le rapport de bug : http://svn.boost.org/trac/boost/ticket/1852
    le patch : http://svn.boost.org/trac/boost/changeset/48190

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

Discussions similaires

  1. [Servlet] Fichiers d'initialisation
    Par david71 dans le forum Servlets/JSP
    Réponses: 7
    Dernier message: 03/09/2003, 13h47
  2. Créer et initialiser un composant TStatusBar :help:
    Par James_ dans le forum C++Builder
    Réponses: 10
    Dernier message: 21/08/2003, 08h52
  3. [servlet] initialisation d'objets
    Par tiPouick dans le forum Servlets/JSP
    Réponses: 11
    Dernier message: 05/08/2003, 12h12
  4. Initialisation de XMLModule
    Par Sylvain Leray dans le forum XMLRAD
    Réponses: 10
    Dernier message: 01/04/2003, 10h08
  5. initialisation Directinput avec delphi
    Par Madmaxx dans le forum DirectX
    Réponses: 1
    Dernier message: 21/02/2003, 17h37

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