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

 C++ Discussion :

Considérations de débutant!


Sujet :

C++

  1. #1
    Membre averti
    Inscrit en
    Avril 2009
    Messages
    45
    Détails du profil
    Informations forums :
    Inscription : Avril 2009
    Messages : 45
    Par défaut Considérations de débutant!
    Bonjour a tous,

    je débute en C++ après avoir (malheureusement pour certains, heureusement pour d'autres) ingéré un gros pavé sur le langage C (Eyrolles, C. Delannoy).
    Voulant faire de la prog de soft mon métier un jour (lointain? ), on m'a conseillé de me tourner plutôt vers le C++, car de plus haut niveau, etc ... (je ne veux pas lancer un troll).

    Bon tout ca pour dire que j'en suis au début du début, j'ai acheté un autre gros pavé sur le C++ (Bjarne Stroustrup, 3ème édition), que je trouve un peu mal traduit et surtout moins accessible. Certaines notions de base importantes sont assez mal détaillées. Je pense notamment à la partie I (types de bases, fonctions, etc...) qui, sans mes connaissances en C, n'auraient pas été bien comprises. En lisant cette partie là, j'ai pris assez peur pour la suite. D'ailleurs, est ce que comme moi certains lecteurs de ce réputé bouquin sont devenus verts en lisant les premiers chapitres?

    Et ca n'a pas manqué puisque le "petit" paragraphe sur les références n'en donne pas assez de détail.
    Comment est ce que le lecteur est censé y trouver un avantage par rapport à un pointeur C classique? Le seul truc que j'ai cru comprendre était qu'une référence était un pointeur constant.

    Ma question donc: pourquoi ne juste pas déclarer un pointeur constant et s'en servir comme référence? Quels sont les avantages (non évidents) d'une référence par rapport à un pointeur?

    Merci à tous!

  2. #2
    Membre expérimenté
    Avatar de Chatanga
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    211
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 211
    Par défaut
    J'ajouterais qu'une référence est un pointeur constant qui ne peut pas être "null". Personnellement, j'ai l'habitude d'utiliser les références en lieu et place des pointeurs constants sur valeurs constantes et non null. En clair, j'utilise une référence lorsqu'un passage par valeur conviendrait, simplement pour l'optimiser (typiquement, "const string &" plutôt que "string"). Dans le cas contraire, je préfère laisser apparent au lecteur de mon code le fait qu'il ne s'agit pas d'un variable "locale".

  3. #3
    Membre expérimenté Avatar de Dalini71
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2008
    Messages
    181
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Février 2008
    Messages : 181
    Par défaut
    Les références sont plus pratiques à utiliser syntaxiquement parlant, et le fait qu'elles ne puissent pas être nulles constitue une "sécurité" supplémentaire.

    Sinon fais quelques recherches sur le forum, il y a beaucoup de posts traitant de la différence pointeurs/références.

  4. #4
    Membre averti
    Inscrit en
    Avril 2009
    Messages
    45
    Détails du profil
    Informations forums :
    Inscription : Avril 2009
    Messages : 45
    Par défaut
    Hola,

    merci pour vos réponses!
    Avez vous appris le C++ avec le Bjarne Stroustrup?

    Si oui, ne le trouvez pas un peu difficile pour débuter?

  5. #5
    Membre expérimenté
    Avatar de Chatanga
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    211
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 211
    Par défaut
    Abstraction faite des cours à la fac qui ne valaient pas tripette, j'ai réellement appris les arcanes du C++ avec le bouquin Thinking in C++ de Bruce Eckel (gratuitement téléchargeable et en français aussi je pense). C'est vraiment un bon bouquin qui va au fond de choses et qui explique tout du C++.

  6. #6
    Membre Expert
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Par défaut
    Citation Envoyé par Chatanga Voir le message
    Abstraction faite des cours à la fac qui ne valaient pas tripette, j'ai réellement appris les arcanes du C++ avec le bouquin Thinking in C++ de Bruce Eckel (gratuitement téléchargeable et en français aussi je pense). C'est vraiment un bon bouquin qui va au fond de choses et qui explique tout du C++.
    Tout? faut pas exagérer non plus. Il est complet certes mais quand même.

    Le BS est en fait plus une bible de référence sur le C++ qu'un véritable bouquin d'initiation.
    Y'a une suggestion de livre sur le site, personnellement j'ai une préférence pour Accelerated C++ mais bon.

  7. #7
    Membre expérimenté Avatar de Dalini71
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2008
    Messages
    181
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Février 2008
    Messages : 181
    Par défaut
    Moi perso j'ai commencé avec Accelerated C++, et j'ai ensuite lu Thinking in C++.

    Les 2 sont très différent dans leur approche et leur méthodologie, mais je dois avouer avoir uen préférence pour Accelerated C++.

    En tout cas les deux sont biens et constituent une bonne initiation.

  8. #8
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    Effectivement, le stroutroup n'est pas vraiment à considérer comme un bouquin d'apprentissage, mais plutôt comme une référence à consulter en cas de doute

    Pour ce qui est de la différence entre les références et les pointeurs:

    D'un point strictement technique, il trois différences majeures:
    • la garantie de non nullité
    • le fait que la constance s'applique toujours à la variable, et non au pointeur ou à la variable pointée selon la position du mot clé const
    • le fait que la syntaxe d'utilisation d'une référence est identique à celle d'utilisation d'une variable normale

    De plus, le passage d'une référence constante en paramètre a l'énorme avantage de permettre la création d'un temporaire non nommé, que ne permet pas le passage par pointeur.

    En effet, si tu as une fonction foo qui prend la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void foo(std::string const & str)
    {
        /*...*/
    }
    il t'est possible de l'appeler sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int bar()
    {
        foo("bonjour");
    }
    où le terme bonjour sera implicitement converti en std::string qui n'existera que le temps de l'appel de la fonction foo().

    Ces trois points et la particularité ci dessus donnent un avantage réel à la référence comparé au pointeur
    En effet, les pointeurs trainent avec eux une très mauvaise réputation de complexité, et il faut avouer qu'elle est relativement justifiée du fait des problèmes auxquels n'importe quel programmeur C a au moins été confronté une fois:
    • Passer un pointeur non initialisé ou pour lequel la mémoire n'a pas été allouée avant à une fonction provoquera une catastrophe
    • oublier de libérer la mémoire allouée à un pointeur avant d'en perdre la place provoquera une fuite mémoire, avec, à terme (la question n'étant pas de savoir si cela arrivera, mais quand), un plantage de l'application, si pas du système, par manque de mémoire
    • Toute tentative d'accès à un élément en dehors de l'espace mémoire alloué à un pointeur peut avoir des résultats pour le moins surprenants, n'apparaissant bien souvent que bien après l'accès ayant provoqué l'erreur
    • J'en oublie surement...
    Au final, la règle la plus cohérente serait:
    • Passer les type primitifs ((unsigned) char / short/ int / long / float / double) par valeur, sauf s'il y a une raison pour que la fonction les modifie et ne renvoie pas cette valeur, au point que,
    • s'il faut éviter la copie de l'objet passé en paramètre, le passer par référence (éventuellement constante si la fonction ne doit pas le modifier), à moins de n'avoir pas d'autre choix que de passer par un pointeur, et, en tout état de cause, chaque fois qu'il faudrait utiliser l'opérateur "address of" ( AKA: l'esperluette " & " ) pour pouvoir passer un pointeur.
    • Passer par pointeur lorsque l'utilisation d'une référence est quasiment impossible, comme:
      • fournir un argument permettant de définir une "référence" (dans le sens général) vers le contenant dans le contenu
      • fournir un argument permettant de définir une "référence" vers un objet de même type
      • fournir un argument destiné à être intégré dans une collection d'objets polymorphes
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  9. #9
    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 Chatanga Voir le message
    Abstraction faite des cours à la fac qui ne valaient pas tripette, j'ai réellement appris les arcanes du C++ avec le bouquin Thinking in C++ de Bruce Eckel (gratuitement téléchargeable et en français aussi je pense). C'est vraiment un bon bouquin qui va au fond de choses et qui explique tout du C++.
    Salut,
    La page tutoriel du site regroupe différents cours de C++ et en particulier Thinking in C++ en anglais et en une traduction française de la rédaction de DVP.

  10. #10
    Membre averti
    Inscrit en
    Avril 2009
    Messages
    45
    Détails du profil
    Informations forums :
    Inscription : Avril 2009
    Messages : 45
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Salut,
    En effet, si tu as une fonction foo qui prend la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void foo(std::string const & str)
    {
        /*...*/
    }
    il t'est possible de l'appeler sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int bar()
    {
        foo("bonjour");
    }
    où le terme bonjour sera implicitement converti en std::string qui n'existera que le temps de l'appel de la fonction foo().
    Et de façon générale

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void foo(type * s)
    {
        /*...*/
    }
    et l'appeler:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int bar()
    {
        foo(&var);
    }
    permet aussi d'utiliser un temporaire, qu'en penses tu?

  11. #11
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par FabTheGeek Voir le message
    Et de façon générale

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void foo(type * s)
    {
        /*...*/
    }
    et l'appeler:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int bar()
    {
        foo(&var);
    }
    permet aussi d'utiliser un temporaire, non?
    ta variable var peut être temporaire au sens où elle n'est déclarée que dans bar, mais elle n'a rien de "non nommée"... Or, c'est ce terme qui est le plus important.

    C'est à dire que, pour autant qu'il y ait possibilité de convertir un type quelconque dans le type attendu comme argument par la fonction, la référence constante permet de créer un objet du type ad-hoc, sans avoir à déclarer une variable du type attendu.

    Pour essayer de te faire comprendre, mettons une classe simple MyClass composée sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class MyClass
    {
        public:
            MyClass(int n) :n_(n){}
            int value() const{return n_;}
        private:
            int n_;
    };
    Du fait de son constructeur, je peux (ici implicitement) convertir n'importe quel entier en un objet de type MyClass

    Et une fonction foo prenant comme argument un objet de type MyClass.

    Avec la référence constante, tu peux écrire un code de bar proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void bar(int i)
    {
        /* i aurait très bien pu être déclaré et défini ici */
        foo(i); // le constructeur assure la conversion implicite int ==>MyClass
        /* on peut faire beaucoup de choses ici sans avoir besoin du type
         * MyClass 
         */
    }
    alors qu'avec un pointeur tu serais obligé de travailler sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void bar(int i)
    {
        /* i aurait très bien pu être déclaré et défini ici */
        MyClass temp(i);
        foo(&temp);
        /* temp continue a exister ici, alors que l'on n'en a peut etre plus 
         * besoin
         */
    }
    la différence vient du fait que tu dois disposer de la variable temp pour pouvoir passer un pointeur dessus...

    Ici, MyClass est très simple, et n'utilise pas énormément de ressources...

    Mais, si MyClass était définie de manière plus complexe, et que, de ce fait, elle monopolisait des ressources importantes (ce peut etre un fichier, un socket, ou, simplement, un espace mémoire important), ces ressources ne seraient libérées, dans la version utilisant un pointeur, que lorsque temp serait détruit, c'est à dire, juste avant l'accolade fermante finale.

    Si, pour une raison ou une autre (multi threading ) il faut pouvoir disposer "par ailleurs" (comprend: dans une autre fonction) des ressources monopolisées par cette instance particulière de la classe, tu cours à la catastrophe.

    Par contre, avec la version utilisant une référence, la variable temporaire est créée juste avant l'appel de foo (selon l'exemple) qui la demande en paramètre, et détruite dés que cette fonction (foo selon l'exemple) est terminée.

    Ce qui signifie que les ressources que la variable pouvait monopoliser sont elles aussi libérées et disponibles pour être réutilisées, en gros dés que l'on a passer le point virgule qui suit l'appel de foo().

    Avoue qu'il est difficile de monopoliser des ressources moins longtemps que cela

    Par contre, cela a un inconvéniant: MyClass doit être passé sous la forme d'une référence constante, ce qui implique l'impossibilité d'appeler des fonctions membres non constantes de l'objet...

    Mais la logique derrière cela est finalement tout simple: il ne sert à rien de permettre à une fonction de modifier cet objet temporaire si, de toutes manières, il est destiné à être détruit dés que la fonction est finie...
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

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

Discussions similaires

  1. Débutant XML
    Par viny dans le forum XML/XSL et SOAP
    Réponses: 8
    Dernier message: 25/07/2002, 13h07
  2. [Kylix] Re Re: débutant sur Kylix et Linux.....
    Par Eclypse dans le forum EDI
    Réponses: 2
    Dernier message: 08/06/2002, 23h53
  3. [Kylix] Le débutant en Kylix et Linux....
    Par Eclypse dans le forum EDI
    Réponses: 2
    Dernier message: 08/05/2002, 11h37
  4. Réponses: 3
    Dernier message: 07/05/2002, 17h06
  5. [HyperFile] 2 questions de débutant
    Par khan dans le forum HyperFileSQL
    Réponses: 2
    Dernier message: 30/04/2002, 00h18

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