nazcafan a écrit 190 commentaires

  • # mouais

    Posté par  . En réponse au journal Google forke C++. Évalué à 9.

    Le projet sera tué en avril prochain, pour le sprint cleaning, et ils crééront un nouveau truc par dessus python pour que Dédé puisse avoir sa promotion et acheter le Porsche Cayenne biturbo.

  • [^] # Re: Obsolescence programmée

    Posté par  . En réponse au journal Une histoire de smartphones. Évalué à 7.

    Il me semble que dans le cas du Nexus 5x, c'était pas vraiment programmé et il y avait un défaut de conception. D'ailleurs le téléphone tombait en panne vers 24 mois, ce qui a provoqué beaucoup de retours pendant la période de garantie (le mien a lâché à 1 an et 11 mois). Si ça avait été programmé, ils l'auraient fait lâcher à 2 ans ½ pour éviter d'avoir à se coltiner tous ces retours

  • [^] # Re: Indice

    Posté par  . En réponse au message Bizarrerie opérateur ternaire (?:). Évalué à 2. Dernière modification le 11 juin 2020 à 11:33.

    L'indice de Cyril t'indique la bonne direction.

    J'ai refait ton truc avec un constructeur de copie et en virant les std::flush et les std::endl, parce que d'une part, dans endl il y a déjà un flush, et d'autre part, tu t'intéresses à la sortie standard du programme une fois terminé, alors tu n'as pas besoin de faire un flush à chaque évènement quantique. Du coup c'est moins lourd à lire.

    #include <iostream>
    
    class my_class {
      char c_;
    public:
      my_class(char c) {
        c_ = c;
        std::cout << "Ctor: " << c_ << '\n';
      }
    
      my_class(const my_class & rhs) : c_(rhs.c_) {
        std::cout << "Cpy: " << c_ << '\n';
      }
    
      ~my_class() {
        std::cout << "Dtor: " << c_ << '\n';
      }
    };
    
    #define M(e)\
      std::cout << "\ntrue ? " << #e << '\n';\
      (true ? e)
    
    int main() {
      my_class A('A'), B('B');
    
      M( A : B );
      M( A : my_class('C') );
      M( my_class('D') : A );
      M( my_class('E') : my_class('F') );
    
      std::cout << "\nEnd main()\n";
    }

    Comme l'indiquait Cyril, une copie est effectuée quand tu invoques true ? A : my_class('C') et pas dans les autres cas. Cette copie est nécessaire pour que les deux arguments de l'opérateur ternaire soient de même type (my_class).
    * Dans la ligne précédente, les deux arguments sont déjà du même type (my_class &) et aucune conversion n'est nécessaire ;
    * Dans la ligne suivante, une conversion serait nécessaire, mais elle n'a pas lieu parce qu'elle est codée dans la branche false de l'opérateur ternaire ;
    * Dans le dernier cas, les deux arguments sont de type (my_class) et aucune conversion n'est nécessaire.

    Un collègue sympa a réécrit le code avec des template pour mettre en évidence les types utilisés :

    #include <iostream>
    
    class my_class {
      char c_;
    public:
      my_class(char c) {
        c_ = c;
        std::cout << "Ctor: " << c_ << '\n';
      }
    
      my_class(const my_class & rhs) : c_(rhs.c_) {
        std::cout << "Cpy: " << c_ << '\n';
      }
    
      ~my_class() {
        std::cout << "Dtor: " << c_ << '\n';
      }
    };
    
    template <typename> char const* type();
    template <> char const* type<my_class&>() { return "my_class&"; }
    template <> char const* type<my_class const&>() { return "my_class const&"; }
    template <> char const* type<my_class>() { return "my_class"; }
    
    #define M(e)\
      std::cout << "\ntrue ? " << #e << '\n';\
      std::cout << "type=" << type<decltype(true? e)>() << "\n"; \
      (true ? e)
    
    int main() {
      my_class A('A'), B('B');
    
      M( A : B );
      M( A : my_class('C') );
      M( my_class('D') : A );
      M( my_class('E') : my_class('F') );
    
      std::cout << "\nEnd main()\n";
    }
  • [^] # Re: probleme avec gets

    Posté par  . En réponse au message problème avec la boucle do while. Évalué à 3.

    classe\projet_reservation_voillier_version1.0\main.c|64|warning: implicit declaration of function 'getch' [-Wimplicit-function-declaration]|
    ||=== Build finished: 0 error(s), 1 warning(s) (0 minute(s), 0 second(s)) ===|
    

    Ça m'a plutôt l'air d'un avertissement à la compilation, comme si le compilateur n'avait pas trouvé la déclaration de getch alors qu'elle est censée se trouver dans l'en-tête conio.h (pourtant inclus dans le code).

  • [^] # Re: Première chose à faire

    Posté par  . En réponse au message problème avec la boucle do while. Évalué à 1.

    Je le vois toujours dégueulasse, le code de son post, t'es sûr que t'as validé ?

  • # pourquoi une boucle ?

    Posté par  . En réponse au message copier les elements d'un tableau dans un fichier. Évalué à 5.

    pourquoi ne pas simplement écrire le dernier élément du tableau plutôt que de boucler sur tout le tableau ?

    Par exemple on pourrait faire ceci :

    bateau[N] = saisie();
    FILE *fichier = fopen("mon_voillier.txt", "a");
    if (fichier != NULL){
        fprintf(fichier,
                "%s %s\n%s\n%s\n%s\n%d/%d/%d\n%d/%d/%d\n \n", 
                bateau[N].un_locataire.nom,
                bateau[N].un_locataire.prenom,
                bateau[i].un_locataire.cni,
                bateau[N].id_reservation,
                bateau[N].id_voillier,
                bateau[i].date_debut.jour,
                bateau[N].date_debut.mois,
                bateau[N].date_debut.annee, 
                bateau[N].date_fin.jour, 
                bateau[N].date_fin.mois,
                bateau[N].date_fin.annee);
        fclose(fichier);
    }
    ++N;

    Quelques remarques :

    • initialiser ton pointeur fichier à NULL ne sert à rien si tu vas le réaffecter à la ligne d'après ;
    • plutôt que d'incrémenter tes variables de façon pédestre, je te conseille d'apprendre à utiliser les opérateurs d'incrémentation du langage, ils sont utilisés partout dans le monde du C ;
    • ton code est extrêmement mal mis en forme, je te conseille d'utiliser un programme de mise en forme automatique de code tel que clang-format, ce sera plus aisé de revoir ton code et de déceler des erreurs ;
    • prends la peine de relire avant de poster, il y a des parties de ton post que j'ai dû relire 4 fois avant de comprendre où tu voulais en venir.
  • [^] # Re: C, ou C++ ? Ça dépend du compilateur.

    Posté par  . En réponse au message les structures en c. Évalué à 1.

    En même temps, il a posté dans le forum C…

  • [^] # Re: 'pouvez répéter la questioooon ?

    Posté par  . En réponse au message Sécurité lors de la déclaration d'un pointeur. Évalué à 1. Dernière modification le 09 novembre 2019 à 10:23.

    Justement dans C11, c'est rédigé différemment, lorsque l'on a affaire à un UB, c'est dit explicitement dans l'article concerné.

    Le standard C89 a 89 occurences (😃) de l'expression behavior is undefined, et ce tout au long du document, par exemple en 3.3.3.2 (Address and indirection operators) alinéa 2

    If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined.

    Par ailleurs l'annexe A.6.2 du C89 (Portability Issues -> Undefined behavior) est aussi présente dans C11, elle a simplement été déplacée en J.2. Le paragraphe sur l'utilisation des variables automatiques dont la valeur est indéterminée, y est toujours présent.
    Par contre, là où tu sembles avoir raison, c'est que l'annexe J est informative, pas normative : elle devrait permettre d'interpréter le standard mais n'a pas valeur de norme. Étrange quand même de garder ça pendant plus de 30 ans dans le document si c'est faux ou douteux (c'est dans le dernier draft de C18)

    Lorsque la variable peut-être collée dans un registre, il va se comporter différemment.
    - mais je crois que la norme mentionne ce cas précis. -

    je pense que tu fais référence à 6.3.2.1, alinéa 2 :

    if the lvalue designates an object of automatic storage duration that could have been declared with the register storage class (never had its address taken), and that object is uninitialized (not declared with an initializer and no assignment to it has been performed prior to use), the behavior is undefined.

  • [^] # Re: 'pouvez répéter la questioooon ?

    Posté par  . En réponse au message Sécurité lors de la déclaration d'un pointeur. Évalué à 1.

    La "synthèse" liste ce cas, tout en faisant référence à des articles … où l'UB n'est pas indiquée.

    Je n'aime pas la façon dont le standard C89 est rédigé, mais je ne pense pas qu'A.6.2 soit une synthèse, mais plutôt une espèce de section spéciale UB (bien que UB soit mentionné à plein d'autres endroits)

    Je ne connais aucun compilo qui s'autorise à invoquer un démon nasal dans ce cas, et où dev/mem ne fonctionnerait pas.

    Je ne prendrais pas ça à la légère, ce type d'UB a été défini avec beaucoup d'attention et si même les dernières version du standard C++ la gardent, c'est que les compilateurs en profitent pour faire des optimisations de code assez tordues. Donc, pas de démon nasal, mais un code qui risque d'être surprenant au moment où tu t'y attends le moins.

  • [^] # Re: 'pouvez répéter la questioooon ?

    Posté par  . En réponse au message Sécurité lors de la déclaration d'un pointeur. Évalué à 3.

    Vous pouvez lancer ce programme autant de fois que vous voulez sous Linux, sous Windows ou BSD, vous ne verrez pas la moindre fuite de mémoire

    J'insiste, il y aura une fuite de mémoire à chaque exécution te ce programme, cette fuite sera résorbée par le système d'exploitation à chaque fin d'exécution, mais fuite de mémoire il y aura.

    Une fuite de mémoire est caractérisée par l'incapacité du programme a libérer lui-même la mémoire qu'il a allouée. Dans l'exemple que je donne, une fois qu'on a quitté la fonction main() on perd l'adresse de la mémoire allouée, ce qui caractérise cette fuite. Je reconnais que l'exemple est un peu tordu dans le sens où, de toutes façons, on ne peut pas faire grand chose en C une fois que le main() est terminé, mais si le code dans le main() était dans une fonction f() qu'on appelait à la chaîne, peut-être serais-tu plus enclin à la voir.

  • [^] # Re: 'pouvez répéter la questioooon ?

    Posté par  . En réponse au message Sécurité lors de la déclaration d'un pointeur. Évalué à 1.

    J'insiste, section A.6.2 Undefined behavior

    The behavior in the following circumstances is undefined:
    […]
    * The value of an uninitialized object that has automatic storage duration is used before a value is assigned (3.5.7).

    Pour les modernes, c'est aussi valable en C++ (j'ai la flemme de sortir le draft pour 17, mais c'est pareil), 8.5 alinea 12

    If an indeterminate value is produced by an evaluation, the behavior is undefined except in the following cases:

    les exceptions en question sont des chars.

  • [^] # Re: 'pouvez répéter la questioooon ?

    Posté par  . En réponse au message Sécurité lors de la déclaration d'un pointeur. Évalué à 2.

    le dernière exemple est faux, output devrait être un pointeur vers int pas juste un int, mea maxima culpa.

  • # 'pouvez répéter la questioooon ?

    Posté par  . En réponse au message Sécurité lors de la déclaration d'un pointeur. Évalué à 3. Dernière modification le 08 novembre 2019 à 18:17.

    donner le mauvais accès à la mémoire réservée par ce pointeur

    un pointeur en soi ne réserve pas de mémoire :

    int main()
    {
        int * input = NULL, 
        int *output = NULL;
        mafonction(output, input, 42);
    }

    Ici aucune mémoire n'a été allouée aux pointeurs input et output donc l'appel à mafonction va déréférencer un pointeur NULL ce qui va engendrer un comportement non-défini, ce qui est à-peu-près passible de la peine capitale pour un programmeur C.

    (Là je suis sympa, il me semble que Linux est pas trop méchant et plante le programme direct quand le pointeur est NULL, par contre si le pointeur n'avait pas été initialisé du tout, c'était des feux d'artifice)
    Tu peux décider d'utiliser de la mémoire sur la pile pour appeler ta fonction:

    int main()
    {
        int input[42]; 
        int output[42];
        mafonction(output, input, 42);
    }

    Ici, on a bien de la mémoire pour l'input et l'output (mémoire de la pile), mais l'appel à mafonction va engendrer la lecture du tableau input qui n'a pas été initialisé, ce qui va provoquer un comportement non-défini, ce qui est à-peu-près passible de la peine capitale pour un programmeur C.

    Tu peux corriger en initialisant les données lues :

    int main()
    {
        int input[] = {0, 1 , 42}; 
        int output[42];
        mafonction(output, input, 42);
    }

    Là, c'est bien on a initialisé les données, mais on a dépassé la taille du tableau input, et on commence à lire et à écrire des données en débordant du tableau , ce qui va provoquer un comportement non-défini, ce qui est à-peu-près passible de la peine capitale pour un programmeur C.

    On peut s'en sortir en contraignant la taille de ton tableau de sortie.

    int main()
    {
        int input[] = {0, 1 , 42}; 
        int output[sizeof(input) / sizeof(int)];//does C11+ have constexpr?
        mafonction(output, input, sizeof(input) / sizeof(int);
    }

    Tu peux aussi décider d'allouer un tableau sur le tas et bien penser à initialiser les données et tout et tout.

    int main()
    {
        cont size_t length = 42;
        int *input  = malloc(length * sizeof(int)}; 
        for (size_t i = 0; i!= length;++i){input[i] = length - i;}    
        int output  = malloc(length * sizeof(int)}; 
        mafonction(output, input, length);
    }

    Mais on aura oublié d'invoquer free afin de libérer la mémoire allouée pour input et output, créant une fuite de mémoire qui est à-peu-près passible de la peine capitale pour un programmeur C.

    C'est le côté fun du C, on donne au programmeur une infinité d'opportunités de se prendre les pieds dans le tapis.

    Bon 'dredi !

  • # Pain béni pour les réactionnaires

    Posté par  . En réponse au journal Féminisation des diplômes, y'a encore du boulot. Évalué à 10.

    Plus on perdra de temps et d'énergie à livrer ce type de combat débile sur la langue et la grammaire, moins on en aura pour les problèmes comme les violences, le harcèlement, l'inégalité d'opportunité, l'inégalité salariale… Qui pourtant mériteraient plus d'attention.

    D'un autre côté, si le titre de leur grade est la plus grande cause de révolte pour ces dames, c'est que le machisme ordinaire dans le milieu de la recherche a dû bien régresser depuis le temps où j'y ai mis les pieds ; ça fait plaisir de voir du progrès.

  • [^] # Re: Hum...

    Posté par  . En réponse au journal Le VAE n'est PAS un truc de fainéant. Évalué à 4.

    Franchement, je suis bluffé par le skateboard et la trottinette électriques. J'utilise quotidiennement des vélos en libre service, et je me suis fait mettre minable l'autre jour par un skateboard électrique. Une semaine après, j'ai discuté avec un mec en trottinette électrique, il m'a dit qu'il avait une autonomie d'un peu moins de 20 bornes.

    Autant, dans les grandes villes, je trouve que la voiture électrique (à part pour la flotte de taxis, utilitaires et autres véhicules spécialisés) est une fausse solution, autant ces appareils là, peut-être plus que le VAE, ont un potentiel énorme : l'encombrement est minimal (on peut le glisser sous son poste de travail), l'autonomie semble correcte pour pas mal d'itinéraires et la vitesse dépasse celle d'un vieux con (bibi) sur son vélo en libre service.
    J'espère que les autorités en France et ailleurs sauront donner un cadre légal pas trop contraignant pour l'utilisation des dits véhicules, quelque chose comme une tolérance s'ils roulent au pas sur les trottoirs, et une circulation autorisée sur la chaussée et les pistes cyclables. Ce serait vraiment dommage de passer à côté d'une solution pareille !

    P.S. là où j'habite, c'est très plat, mais ça ce défend dans les côtes, ces engins là ?

  • # Le début de la fin

    Posté par  . En réponse au journal Écoles d'ingénieurs: les frais augmentent. Évalué à 10.

    L'intérêt des écoles d'ingénieur à la française, c'était de pouvoir faire une sélection sur le niveau et pas sur le fric, pour donner un semblant d'égalité des chances. Je sais bien que c'était contourné dans une certaine mesure par des parents aisés, que ça n'empêchait pas les élites de se renouveler, mais quelqu'un de bon et de bosseur pouvait y arriver, même s'il était issu d'une famille peu aisée.

    Le gouvernement est en train de suivre le schéma emprunté par le Royaume Uni il y a quelques années : première phase : introduction des frais d'inscription ou de scolarité, deuxième phase : explosion des coûts. Aujourd'hui, les grandes universités britanniques (Oxbridge et Imperial) chargent 9 250 £ / an, ce qui nous amène à une dette de 52 000 € pour un étudiant en sortie de master (et encore, la livre a dégueulé). Rajoutez les frais de logement et la dette monte encore plus haut ; de quoi faire réfléchir des gens qui n'ont pas les parents pour assurer le coup financièrement si jamais le début de carrière est turbulent.

    Si les gouvernements successifs continuent de suivre ce chemin tout tracé, cette politique va gentiment achever le dernier vestige de l'ascenseur social qui subsiste en France.

    En Angleterre, c'est passé comme une lettre à la poste, les étudiants n'avaient probablement pas assez de pouvoir de nuisance, et les gens plus âgés à qui j'ai parlé trouvaient ça tout à fait normal que les générations suivantes payent pour une éducation dont ils avaient bénéficié gratuitement quelques années plus tôt.

    pour mettre en place dès la rentrée prochaine un dispositif commun qui prendra en compte les étudiants lésés par cette décision.

    J'attends de voir ce dispositif, mais d'ici, ça semble être un truc pipeau pour faire passer la pilule, j'hésite entre une cellule de soutien psychologique ou un prêt étudiant à des taux usuriers et irrévocable en cas de faillite personnelle.

  • # problème A -> B

    Posté par  . En réponse au message Le constructeur d'une classe de base peut-il savoir qu'il n'est pas le dernier?. Évalué à 2.

    Je pense que ce que tu cherches à faire est impossible, et j'ai l'intuition que le vecteur dont la taille change selon la classe est une mauvaise solution B à un problème A que j'aimerais bien connaître.

  • [^] # Re: quelques éléments de réponse

    Posté par  . En réponse au message classe C++, membre structure C et allocation dynamique. Évalué à 5.

    Dans quel cas faut-il implémenter un deleter pour un unique_ptr ? Notamment si je dois nettoyer la structure pointée avant qu'elle soit libérée ? Le deleter par défaut est appelé par le destructeur de MaClasse ?

    Le deleter par défaut est appelé par le destructeur de unique_ptr après que le destructeur de ta classe a fini de s'exécuter (cf ma première réponse). En l’occurrence, tu pourrais le remplacer par un Deleter qui appelle la fonction de nettoyage C avant de libérer la mémoire :

    #include <memory>
    #include <iostream>
    #include <exception>
    
    extern "C"
    {
    struct my_c_struct {int data;};
    int s_init(my_c_struct * c){ std::cout << "C initializing\n"; return 1;}
    void s_destroy(my_c_struct *c){ std::cout << "C clean up\n";}
    }
    
    class MyClass
    {
    public:
      MyClass();
    private:
      struct Deleter
      {
          void operator()(my_c_struct * p)
          {
              s_destroy(p);
              delete p;
          }
      };
      std::unique_ptr<my_c_struct, Deleter> s; 
    };
    
    MyClass::MyClass()
    : s(new my_c_struct)
    {
        int rc = s_init(s.get());
        if (rc != 0)
        {
            throw std::runtime_error("could not initialize c_struct, rc = " + std::to_string(rc));
        }
    }
    
    int main()
    {
        try
        {
            MyClass m;
            // allocation s'est bien passée, je peux continuer ?
        }
        catch (std::exception const& e)
        {
            std::cout << "runtime error: " << e.what() << '\n';
            return 42;
        }
        return 0;
    }

    C'est une approche un peu bâtarde à mon goût parce que les responsabilités d'initialisation et de de nettoyage C ne sont pas du ressort du même objet : l'initialisation est faite dans le constructeur de MyClass et le nettoyage dans le Deleter du unique_ptr. Du point de vue ingénierie, ce n'est pas particulièrement idéal, d'ailleurs tu noteras que le code de nettoyage C est lancé même si l'initialisation échoue. Ça dépend probablement de ton API C, mais en général, c'est inutile, voire dangereux. Pour le coup, il serait peut-être préférable de laisser la responsabilité de gérer la mémoire au unique_ptr et de laisser à ta classe de gérer l'initialisation / nettoyage :

    #include <memory>
    #include <iostream>
    #include <exception>
    
    extern "C"
    {
    struct my_c_struct {int data;};
    int s_init(my_c_struct * c){ std::cout << "C initializing\n"; return 1;}
    void s_destroy(my_c_struct *c){ std::cout << "C clean up\n";}
    }
    
    class MyClass
    {
    public:
      MyClass();
      ~MyClass();
    private:
      std::unique_ptr<my_c_struct> s; 
    };
    
    MyClass::MyClass()
    : s(new my_c_struct)
    {
        int rc = s_init(s.get());
        if (rc != 0)
        {
            throw std::runtime_error("could not initialize c_struct, rc = " + std::to_string(rc));
        }
    }
    
    MyClass::~MyClass()
    {
        s_destroy(s.get());
    }
    
    int main()
    {
        try
        {
            MyClass m;
            // allocation s'est bien passée, je peux continuer ?
        }
        catch (std::exception const& e)
        {
            std::cout << "runtime error: " << e.what() << '\n';
            return 42;
        }
        return 0;
    }

    Ici, le code de nettoyage C n'est appelé que si l'initialisation C a abouti.

    / et je gère le fait que l'allocation s'est mal passée ?

    Le catch va récupérer toutes les erreurs, notamment les erreurs d'allocation, et l'exception due à une mauvaise initialisation en C. Mais au moins toutes les ressources auront déjà été libérées au moment du catch, en gros, à ce niveau tu n'as plus qu'à logguer, tout l reste est déjà « géré ». Le fait de confier la libération des ressources aux destructeurs des objets te permet d'avoir une logique try - catch relativement simple comparé à d'autres langages.

  • [^] # Re: quelques éléments de réponse

    Posté par  . En réponse au message classe C++, membre structure C et allocation dynamique. Évalué à 2.

    Cela m'intéresse aussi, mais, hum, ça sera pour la deuxième semaine. Comment utiliser un unique_ptr si je dois passer ce pointeur à une fonction C qui le modifie (ou qui modifie la valeur de certains membres de la structure pointée) ?

    Tu peux utiliser unique_ptr::get :

    #include <memory>
    #include <iostream>
    
    struct Blah
    {
        int value;
    };
    
    int main()
    {
       std::unique_ptr<Blah> unique{new Blah()};//zero-initialization
       std::cout << unique->value << '\n';//0
       Blah * ptr = unique.get();
       ptr->value = 42;
       std::cout << unique->value << '\n';//42
    }
  • [^] # Re: quelques éléments de réponse

    Posté par  . En réponse au message classe C++, membre structure C et allocation dynamique. Évalué à 3. Dernière modification le 22 avril 2017 à 00:47.

    Ben, c'était mon plan de départ, mais j'ai cru comprendre (peut-être par erreur) que le lancement d'une exception dans un constructeur laisse la construction de l'objet inachevée, et que donc son destructeur n'est pas appelé au moment opportun. Si j'avais déjà alloué des trucs au moment du lancement de l'exception, il faut que je fasse le ménage avant de lancer l'exception ?

    C'est une question pertinente. Ce que tu décris est juste, mais une nuance t'échappe. Effectivement, si le constructeur d'un objet émet une exception, l'objet n'est pas considéré comme construit et son destructeur n'est pas appelé. Toutefois, le destructeur des membres et le destructeur des classes de base sont appelés.
    Ce qui m'amène à une réponse plus complète : effectivement, si une exception est lancée depuis le constructeur au milieu de l'allocation de différentes ressources, les libérer proprement risque d'être particulièrement ardu. En conséquence, il est fortement déconseillé pour une classe C++ de gérer directement plus d'une seule ressource. Les autres ressources doivent être gérées par des membres ou des classes de base, dont le destructeur (et donc la libération de la ressource) sera appelé automatiquement par le langage, même dans le cas où l'exception est lancée dans le constructeur.

  • # quelques éléments de réponse

    Posté par  . En réponse au message classe C++, membre structure C et allocation dynamique. Évalué à 4. Dernière modification le 21 avril 2017 à 17:15.

    • En ce qui concerne new VS malloc pour allouer une struct C, je n'ai pas vraiment d'avis ; tant que tu les utilises correctement, ça na va pas changer l'univers. new peut utiliser un autre allocateur que malloc mais tant que tu ne mélanges pas malloc/free avec new/delete sur le même objet, ça ira.
    • La spécification C++ dit que si new échoue à allouer de la mémoire, il émet une exception de type std::bad_alloc, du coup, il est inutile de tester le pointeur de retour envers nullptr.
    • Personnellement, je décourage l'utilisation d'une fonction public du genre init(). Ça laisse plus d'opportunités à l'utilisateur de la classe de se tirer une balle dans le pied. Je suis partisan d'insérer le code d'init dans le constructeur et de balancer une exception en cas d'erreur. Au moins l'utilisateur ne se retrouvera jamais avec un objet inutilisable.
    • si tu as testé le pointeur à la construction, le tester à la destruction est excessif.
    • tu peux probablement déléguer la gestion de ton pointeur à un pointeur intelligent tel que unique_ptr, en définissant le Deleter idoine.
  • # question innocente…

    Posté par  . En réponse au journal Java dans le navigateur : ce n'est pas fini, ça sera pire !. Évalué à 8.

    Est-ce que ça peut faire tourner Rhino ?

  • # Ambiance

    Posté par  . En réponse au journal Faut tout faire soi-même !. Évalué à 10.

    Je travaille à Londres et l'ambiance est plutôt morose, ici. La plupart des gens sont conscients de combien l'Europe a apporté depuis une vingtaine d'années. En Angleterre, le vote "Leave" semble avoir gagné surtout en Province (excepté quelques grandes villes). Peut-être que les richesses que la capitale a amassées n'ont pas été distribuées suffisamment équitablement et que les Anglais l'ont fait savoir à leurs dirigeants.

    Les temps qui arrivent s'annoncent tumultueux, certains parlent déjà d'un second referendum, mais je ne vois pas trop comment le prochain premier ministre (Boris Johnson semble pressenti) pourra ou voudra décemment proposer ça.

    De maniérè plus générale, j'ai peur du précédent que ça a créé… J'ai l'impression que si les défauts majeurs que les dernières crises on révélé dans l'UE (déficit démocratique avec une commission encore trop puissante, mauvaise intégration des économies plus "faibles" dans la monnaie unique, et une gestion inhumaine et calamiteuse de la question des migrants et des frontières extérieures), alors elle est condamnée a se déliter au cours des prochaines années.

  • [^] # Re: peut-être ceci ?

    Posté par  . En réponse au message Petit soucis avec les shared_ptr. Évalué à 2.

    Mec, le but des shared_ptr, unique_ptr et autres est d'implanter une notion de propriété (ownership) qui, en gros représente la responsabilité de détruire l'objet et libérer la mémoire sur laquelle il a été construit.
    Si l'objet est global ou qu'il est alloué sur la pile, il est détruit automatiquement quand le programme s’arrête ou quand le programme quitte le scope dans lequel il a été déclaré. En conséquence, il n'y a aucun intérêt à créer un pointeur intelligent dessus.

    Si tes objets sont placés dans un graphe, cette responsabilité devrait revenir soit au graphe lui même, soit à des objets intermédiaires, par exemple les vector que tu utilises dans ton implantation. Su tu utilises un <vector<shared_ptr<T>>, les shared_ptr auront cette responsabilité, avec un effet de bord : tu pourras alors avoir détruit ton objet graphe et toujours avoir des T non-détruits si jamais tu as gardé des copies de shared_ptr. À toi de décider si c'est une bonne ou mauvaise chose .

  • [^] # Re: peut-être ceci ?

    Posté par  . En réponse au message Petit soucis avec les shared_ptr. Évalué à 1. Dernière modification le 03 juin 2016 à 17:58.

    aussi, tu peux t'assurer facilement du fonctionnement de la mécanique de comptage en mettant p2 dans un scope :

      auto p1 = make_shared<MyInt>(MyInt::get(3));
    
      cout << "p1 : id = " << p1->get_id() << ", n_ptr = " << p1.use_count() << ", addr = " << p1.get() << endl;
      {
          auto p2 = p1;
    
          cout << "p1 : id = " << p1->get_id() << ", n_ptr = " << p1.use_count() << ", addr = " << p1.get() << endl;
          cout << "p2 : id = " << p2->get_id() << ", n_ptr = " << p2.use_count() << ", addr = " << p2.get() <<  endl;
      }
      cout << "p1 : id = " << p1->get_id() << ", n_ptr = " << p1.use_count() << ", addr = " << p1.get() << endl;

    résultat :

    Nb de MyInt : 5
    p1 : id = 3, n_ptr = 1, addr = 0x8289030
    p1 : id = 3, n_ptr = 2, addr = 0x8289030
    p2 : id = 3, n_ptr = 2, addr = 0x8289030
    p1 : id = 3, n_ptr = 1, addr = 0x8289030