dalfab a écrit 6 commentaires

  • # Bien suivre les allocations mémoire

    Posté par  . En réponse au message implémentation d'une liste chaînée en langage c. Évalué à 5.

    Je confirme, ce n'est pas la valeur allouée qui détruite.

    Quand on alloue de la mémoire, la fonction malloc() retourne un pointeur. Ce pointeur sert à 2 choses:
    - il désigne la zone où on y mettra des données
    - il ne faut pas perdre cette valeur, car il faudra la fournir à free() au moment de libérer cette mémoire.

    Ici tu mémorises dans num une zone allouée.
    Plus loin tu appelles list_rem_next(&list, le, &num);, et cette fonction va écraser ce qu'il y a dans num pour le remplacer par l'adresse de élément retiré de la liste. Les éléments insérés en *data dans la liste sont &a[0] &a[1] &a[2] &a[3], et au retour de list_rem_next(&list, le, (void**)&num);, num vaut un de ces 4 pointeurs. Eux pointent dans ton tableau qui est de la mémoire locale sans allocation, donc pas de libération à faire ici!

    Il ne faut, dans ce cas, rien allouer dans num et ne rien libérer à la fin.

    PS: et fais attention à ne pas apprendre un C trop ancien. Dans les années 80, on utilisait des macros pour optimiser des traitements courts, problème ces macros sont:
    - difficile à lire/écrire
    - sources d'erreurs : transcodage lié au principe des macros et non vérification des types.
    Depuis les années 90, on utilise à la place les fonctions inline qui n'ont pas ces handicaps, elles ont été officialisées bien après (en 1999).

  • # a : b

    Posté par  . En réponse au message [résolu] a:b ??. Évalué à 5. Dernière modification le 28 septembre 2022 à 19:30.

    Bonjour,

    Le code définit une structure nommée a, et indique qu'elle hérite de la structure nommée b.
    On le voit plus souvent sous la forme:

        struct a : public b {
            int  bli, bla, blou;
        };
  • # Revenir à pourquoi une telle contrainte.

    Posté par  . En réponse au message probleme pour faire un timer précis de l'ordre de la milliseconde. Évalué à 4.

    Bonjour,

    Il faudrait peut-être revenir à pourquoi tu as ce besoin de timing ultra précis.
    Si juste avant l'échéance une interruption réseau ou disque déclenche c'est une centaine de µs de perdues. Si on a les 2 et qu'en plus le processeur doit sortir de veille c'est 300µs d'écart. C'est inévitable quelle que soit la priorité de ton application. Je travaille sur des noyaux temps réel et je descend au mieux à la milliseconde d'incertitude et toi tu souhaites quelques dizaines de µs de fluctuation et en plus sous Linux.

    Sur une carte dédiée, on peut avoir une contrainte beaucoup plus forte. Pour reprendre mon cas, je dois récupérer des événements toutes les secondes et utiliser leur durée. J'ai une contrainte de 0.0000015ms sur la mesure de cette durée. Aucun problème la durée est garantie et est lue toutes les secondes environ.

    Donc si tu as besoin d'un contrainte aussi forte, il faut peut-être revenir au pourquoi et trouver un moyen de la garantir. Et il faut toujours se poser la question quelles sont les conséquences si la contrainte n'est pas atteinte en séparant les cas : écart maximum fréquent et écart maximum exceptionnel.

  • # que devrait retourner au getter?

    Posté par  . En réponse au message conteneur en retour de fonction. Évalué à 6.

    Bonjour,

    Que doit retourner un getter? Est-ce une copie de ce qui est dans l'objet ou est-ce un moyen d'accéder à ce qui est dans l'objet? Tu as choisi de retourner une copie, pourquoi pas.

    Maintenant tu appelles 2 fois la fonction getvect(), elle te retourne donc à chaque fois une copie. Et bien évidemment tu ne peux pas aller du début d'une copie à la fin d'une autre copie! Quand tu appelles 2 fois une fonction comme tu l'as fait, tu peux t'attendre ne pas toujours avoir le même résultat. Il faudrait donc écrire:

            auto vect = a.getvect();
            for ( auto it = vect.begin(); it != vect.end(); it++ )
                std::cout << *it;

    ou plus simplement:

            for ( auto item : a.getvect() )
                std::cout << item;

    Mais le plus souvent on préfère que le getter retourne une référence constante à ce qui est dans l'objet. En écrivant:

                std::vector<int>const& getvect()const
                {
                    return i;
                }

    on donne la possibilité à celui qui appelle getvect() d'utiliser directement la donnée incluse ou bien d'en faire une copie. Alors mes 2 exemples et ton code fonctionnent. L'inconvénient de cette méthode est que ce qui est retourné est non modifiable. Mais c'est plutôt un avantage, c'est quand même dangereux de permettre à une entité externe d'agir sur des données interne à ton objet.

    Le moyen de donner cet accès en modification, c'est le code que t'as indiqué @Dareg. Mais c'est plutôt à éviter.

  • [^] # Re: Réponse

    Posté par  . En réponse au message Fonction standard : vérifier si des entiers sont consécutif.. Évalué à 1. Dernière modification le 22 décembre 2021 à 10:45.

    Si la fonction correspondant à ton cas existait, elle devrait s'appeler "vérifier_si_les_éléments_potentielement_non_ordonnés_et_tous_différents_constituent_une_séquence_d_éléments_successifs", non cette fonction n'existe pas et serait finalement plus longue à écrire que ton code ;-)

  • # trier ou ne pas trier

    Posté par  . En réponse au message Fonction standard : vérifier si des entiers sont consécutif.. Évalué à 1.

    Tu ne précises pas si la liste doit être ordonnée ou s'ils doivent être consécutifs après ordonnancement.
    Ils sont consécutifs si et seulement si ils sont triés (ou après les avoir triés) et l'écart entre les extrêmes est le nombre d'éléments.

    bool consecutive =  vector_.empty()
                     || (   std::is_sorted(vector_.begin(), vector_.end())
                         && vector_.size() == vector_.back()-vector_.front()+1u);

    Dans le second cas, le plus simple me semble être de les trier

    std::sort(vector_.begin(), vector_.end());
    bool consecutive =  vector_.empty()
                     || vector_.size() == vector_.back()-vector_.front()+1u;

    Mais si tu les présuppose uniques, ta solution est plutôt bonne et marche aussi pour des entiers signés en forçant une comparaison non signée : (*min_max.second - *min_max.first) + 1u != count_).