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 :

initialisation de variable


Sujet :

C++

  1. #1
    Membre averti Avatar de zancrows
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2016
    Messages
    155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2016
    Messages : 155
    Points : 346
    Points
    346
    Par défaut initialisation de variable
    Bonjour,

    j'ai décidé depuis peu de me remettre au C++ que j'ai vu en BTS il y à quelques années. je suis un tuto pour me mettre à jour et découvrir le C++ moderne.
    La ou je me pose une question c'est sur l'initialisation des variables:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    int a = 2;
    int b {2};
    Ma question c'est quelle est la différence, ou ce qu'apporte la syntaxe d'initialisation avec les {}.
    en cherchant un peu j'ai vu qu'elle permettait d'indiquer avec des warnings ce genre de chose:
    mais y a-t-il d'autres raisons ? et faut-il tout le temps utiliser cette syntaxe ?

  2. #2
    Membre régulier
    Homme Profil pro
    Ingénieur validation
    Inscrit en
    Août 2018
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur validation
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2018
    Messages : 37
    Points : 123
    Points
    123
    Par défaut
    La syntaxe int a = 2; a le mérite d'être compatible avec le C historique.
    Pour un type de base, je la trouve aussi un peu plus lisible que la nouvelle, puisqu'elle montre bien qu'on affecte explicitement une valeur initiale lors de la définition de la variable.

    La nouvelle syntaxe a tout de même des avantages majeurs. Elle est unifiée, permet l'initialisation de vecteurs, et lève certaines ambiguïtés.
    Si tu regardes les expressions suivantes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    //  std::vector<int> v01 = 5;   // interdit (ce n'est pas un appel à une affectation, mais à un constructeur explicite)
        std::vector<int> v02(5);    // crée un vecteur de cinq entiers initialisés à zéro
        std::vector<int> v03{5};    // crée un vecteur de un seul entier égal à 5.
        std::vector<int> v05(5,4);  // crée un vecteur de cinq entiers initialisés à 4
        std::vector<int> v04{5, 4}; // crée un vecteur de deux entiers initialisés à 5 et 4
    Avec des types personnalisés :

    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
    // Objet à sémantique de valeur
    class MonObjet{
    	int i;
    public:
            // constructeur par défaut
    	MonObjet(){
    		i = 0;
    	};
            // constructeur surchargé
    	MonObjet(int j){
    		i = j;
    	};
            // constructeur par copie
    	MonObjet(const MonObjet & ref){
    		i = ref.i;
    	};
            // Opérateur d'affectation
    	MonObjet& operator= (const MonObjet & ref){
    		i = ref.i;
    	};
    	~MonObjet(){};
    };
    Dans le code suivant, il est facile de croire qu'on utilise l'opérateur d'affectation alors qu'on utilise toujours des constructeurs.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
       MonObjet o01; // appel au constructeur par défaut
     
        MonObjet o02 = 5;     // appel au constructeur surchargé
        MonObjet o03 (5);     // appel au constructeur surchargé
        MonObjet o04 { 5 };   // appel au constructeur surchargé
     
        MonObjet o05 = o01;   // appel au constructeur par copie
        MonObjet o06 ( o01 ); // appel au constructeur par copie
        MonObjet o07 { o01 }; // appel au constructeur par copie
    Si on ajoute le mot clé explicit devant le constructeur surchargé, la ligne MonObjet o02 = 5; provoque une erreur.
    Si on ajoute le mot clé explicit devant le constructeur par copie, la ligne MonObjet o05 = o01; provoque une erreur.

  3. #3
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    L'unicorn syntax (jeu de mots volontaire) part d'une volonté d'uniformiser et simplifier des choses, mais au final on rajoute de nouveaux cas particuliers pas forcément bien venus.

    Typiquement

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    int a {} ; // initialisation forcée avec le constructeur par défaut, qui initialise à 0 sur les scalaires
     
    std::vector<int> v1 {5, 6}; // vecteur de 2 éléments: 5 et 6
    std::vector<int> v1 (5, 6); // vecteur de 5 éléments: tous des 6

    Sur beaucoup de types qui en gros ne sont pas des collections, cette distinction n'existera pas et les accolades finiront par appeler les constructeurs avec même nombre d'éléments que de paramètres (compatibles)
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  4. #4
    Membre averti Avatar de zancrows
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2016
    Messages
    155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2016
    Messages : 155
    Points : 346
    Points
    346
    Par défaut
    Merci pour ces explications, si je comprend bien sur les types primitifs ça n'a que peu d'incidence.

  5. #5
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    739
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 739
    Points : 3 627
    Points
    3 627
    Par défaut
    Sur les types primitifs, à part la vérification des bornes, non, ça ne change rien. Mais la vérification peut aussi se faire sans mettre en dur une valeur: mettre une variable de type long long dans un int va aussi donner une erreur.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void foo(long long x)
    {
      int y {x}; // erreur
    }
    La syntaxe {} permet aussi d'initialiser les membres sans devoir mettre un constructeur:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    struct Vec2 { int x,y; };
    Vec2 vec2 {1,2};

  6. #6
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 471
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 471
    Points : 6 109
    Points
    6 109
    Par défaut
    Citation Envoyé par jo_link_noir Voir le message
    mettre une variable de type long long dans un int va aussi donner une erreur.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void foo(long long x)
    {
      int y {x}; // erreur
    }
    Avec GCC 8.2.0, j'ai un avertissement quand -Wnarrowing est actif, mais pas d'erreur de compilation.
    Dans la page direct initialization de en.cppreference.com, je n'ai pas vu de règle spéciale qui différenciait T object ( arg ); et T object { arg }; dans le cas où T n'était ni un type de tableau, ni une classe.

  7. #7
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    739
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 739
    Points : 3 627
    Points
    3 627
    Par défaut
    à mon avis, c'est plus un non-respect du standard par gcc qu'autre chose pour compiler facilement d'ancien code qui initialise directement des structures C, et c'est toujours mieux qu'aucun avertissement. Il faudrait vérifier s'il doit y avoir un diagnostic ou une erreur. Je penche pour la seconde d'après https://en.cppreference.com/w/cpp/la...nitialization:

    Otherwise (if T is not a class type), if the braced-init-list has only one element and either T isn't a reference type or is a reference type that is compatible with the type of the element, T is direct-initialized (in direct-list-initialization) or copy-initialized (in copy-list-initialization), except that narrowing conversions are not allowed.
    (Note: avec clang c'est une erreur)

  8. #8
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 471
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 471
    Points : 6 109
    Points
    6 109
    Par défaut
    En effet, après avoir recherché dans N4659 (C++17 final draft), dans la section 11.6.4 List-initialization, je suis tombé sur :
    Citation Envoyé par N4659
    Otherwise, if the initializer list has a single element of type E and either T is not a reference type or its referenced type is reference-related to E, the object or reference is initialized from that element (by copy-initialization for copy-list-initialization, or by direct-initialization for direct-list-initialization); if a narrowing conversion (see below) is required to convert the element to T, the program is ill-formed.
    [ Example:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int x1 {2}; // OK
    int x2 {2.0}; // error: narrowing
    — end example ]

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

Discussions similaires

  1. memset, initialisation de variables.
    Par sympho dans le forum C
    Réponses: 4
    Dernier message: 31/12/2005, 21h20
  2. Réponses: 11
    Dernier message: 07/04/2005, 10h20
  3. [VB.NET] Initialiser les variables
    Par Dnx dans le forum ASP.NET
    Réponses: 8
    Dernier message: 06/04/2005, 16h22
  4. [VB6]Initialiser une variable Static dans un évenement
    Par loverdose dans le forum VB 6 et antérieur
    Réponses: 16
    Dernier message: 20/01/2005, 14h57
  5. Réponses: 9
    Dernier message: 29/06/2004, 08h40

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