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 :

Constructeurs par défaut et constructeur par recopie.


Sujet :

C++

  1. #1
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut Constructeurs par défaut et constructeur par recopie.
    Salut!

    Pour créer un tableau de 10 objets:
    A t[10];
    utilise le constructeur par défaut.
    1)Comment avoir un tableau d'objets construits avec un autre constucteur?

    Ce 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
    22
    23
    24
    #include <iostream>
     
     
    class A{
          public:A(){std::cout<<"default constructor"<<std::endl;}
          public:A(A const &a){std::cout<<"copy constructor"<<std::endl;}
          public:A& operator=(A const &a){std::cout<<"assignement operator"<<std::endl;}
          };
     
    A f(A a){
          std::cout<<"f"<<std::endl;
          A c;
          return c;
          }
     
     
    int main(void){
     
        A a;
        A b=f(a);
     
        system("pause");
        return EXIT_SUCCESS;
    }
    affiche:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    default constructor
    copy constructor
    f
    default constructor
    -la première ligne correspond à la construction de "a";
    -la deuxième à sa recopie lors du passage en paramètre;
    -la quatrième à la construction de "c".

    2)Mais pourquoi n'y a t'il pas à la suite un appel au constructeur par recopie lors de la création d'un objet temporaire au retour de la fonction?
    Est-ce une optimisation?

    3)Pourquoi n'y a t'il pas d'appel au constructeur par recopie lors de la construction de "b"?

    Merci.
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

  2. #2
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    1) Impossible tel quel. Tu peux toujours utiliser un std::vector si ça ne gène pas.

    2) A moins que je ne dise une connerie, oui c'est une optimisation.

    3) L'affectation qui suit une déclaration (ie. sur la même ligne) utilise le constructeur par copie. Si tu sépares déclaration et affectation sur deux lignes là tu auras bien un appel à l'opérateur d'affectation.

    EDIT pour la question 3 : encore une optim certainement ?

  3. #3
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    La question 3) vient d'être modifié.
    Merci.
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

  4. #4
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    Merci de ta réponse.
    Pour les "vector" comment procéder?
    ?
    Ceci:
    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
    23
    #include <iostream>
    #include <vector>
     
    class A{
          public:A(){std::cout<<"default constructor"<<std::endl;}
          public:A(int n){std::cout<<"constructor"<<std::endl;}
          public:A(A const &a){std::cout<<"copy constructor"<<std::endl;}
          public:A& operator=(A const &a){std::cout<<"assignement operator"<<std::endl;}
          };
     
    A f(A a){
          std::cout<<"f"<<std::endl;
          A c;
          return c;
          }
     
     
    int main(void){
    	std::vector<A> v(10);
    	v.assign(10,A(1));
            system("pause");
    	return EXIT_SUCCESS;
    }
    affichant:
    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
    default constructor
    copy constructor
    copy constructor
    copy constructor
    copy constructor
    copy constructor
    copy constructor
    copy constructor
    copy constructor
    copy constructor
    copy constructor
    constructor
    assignement operator
    assignement operator
    assignement operator
    assignement operator
    assignement operator
    assignement operator
    assignement operator
    assignement operator
    assignement operator
    assignement operator
    Pas vraiment optimisé.
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    258
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Bas Rhin (Alsace)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 258
    Points : 307
    Points
    307
    Par défaut
    Citation Envoyé par seriousme
    Pas vraiment optimisé.
    Non, mais il n'y a pas vraiment moyen d'optimiser plus. Lorsqu'un vector a une taille donnée, tu as la garantie que tous ses éléments ont été construits. Si tu veux différer cette construction, tu peux utiliser reserve pour allouer la mémoire puis plus tard construire effectivement les objets.

  6. #6
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    La fonction membre assign, comme son nom l'indique, effectue une affectation. Si tu veux utiliser autre chose que le constructeur par défaut il faut le spécifier lors de la construction (ajout) d'un élement.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    std::vector<A> v(10, A(1));
     
    v.push_back(A(2));

  7. #7
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    C'est noté, merci de vos réponses.
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

  8. #8
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par Laurent Gomila
    2) A moins que je ne dise une connerie, oui c'est une optimisation.
    C'est une optimisation qui n'en est pas une... Une optimisation n'est pas sensée changer le sens d'un programme. Or, ici, le test montre bien que le programme est modifié. Dans le cas général, un compilateur n'aurait pas le droit de faire cette optimisation.

    Dans ce cas particulier, on se trouve dans un cas où le standard a spécifié qu'on avait le droit de faire ça, et si le contructeur par recopie fait des choses non standards (comme afficher du code de débug), tant pis. Cette règle du C++ est généralement appelée (à tort donc) RVO (return value optimisation). On entends aussi régulièrement parler de NRVO, named return value optimisation, ce qui n'est rien d'autre qu'une façon d'aider le compilateur à effectuer cette "optimisation" en écrivant le code d'une manière où il s'y retrouve mieux.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  9. #9
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    Cette règle du C++ est généralement appelée (à tort donc) RVO (return value optimisation).
    Est-il possible de l'empêcher?
    en écrivant le code d'une manière où il s'y retrouve mieux.
    Y a t'il des règles d'écritures particulières?
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

  10. #10
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par seriousme
    Est-il possible de l'empêcher?
    Pas que je sache. Tu peux regarder les options de ton compilateur, on ne sait jamais. En quoi elle te gêne ? Uniquement pour des histoires de compréhension de code, ou parce qu'elle modifie le "vrai" comportement de ton code ? Dans le second cas, j'ai envie de dire que j'ai des doutes sur l'implémentation du constructeur par recopie...

    Citation Envoyé par seriousme
    Y a t'il des règles d'écritures particulières?
    Je ne les connais pas vraiment. Je crois que les compilos se débrouillent mieux quand il y a un point de sortie unique, ou encore que faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    return MaClasse(Arguments);
    A plus de chance de passer que faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    MaClass c;
    //...
    return c;
    Qui lui même est bien plus simple que :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    MaClass a, b;
    if (...) return a; else return b;
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  11. #11
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par JolyLoic
    Qui lui même est bien plus simple que :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    MaClass a, b;
    if (...) return a; else return b;
    Je doute que le compilateur arrive à utiliser du NRVO dans ce cas: cette technique consiste à construire l'objet retourné directement à la place du temporaire. Comme ici il y a deux possibilités, c'est difficile de le faire. Ca fournit indirectement une réponse à celui qui voulait savoir comment faire pour l'empécher. Mais je me demande si la réponse est bien utile.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  12. #12
    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
    Points : 4 625
    Points
    4 625
    Par défaut
    On entends aussi régulièrement parler de NRVO, named return value optimisation, ce qui n'est rien d'autre qu'une façon d'aider le compilateur à effectuer cette "optimisation" en écrivant le code d'une manière où il s'y retrouve mieux.
    Non, en fait c'est l'inverse.

    La RVO c'est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Thing foo()
    {
        return Thing();
    }
    Et NRVO c'est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Thing foo()
    {
        Thing t;
        return t;
    }
    "Named" parce qu'on nomme la variable locale, qui du coup n'est plus une variable temporaire de la valeur de retour.
    Boost ftw

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

Discussions similaires

  1. [SP-2013] Ouvrir par défaut une navigation par métadonnées
    Par rigol'man dans le forum SharePoint
    Réponses: 4
    Dernier message: 05/11/2014, 11h40
  2. Réponses: 11
    Dernier message: 13/08/2014, 00h00
  3. Réponses: 0
    Dernier message: 27/05/2009, 08h58
  4. Réponses: 4
    Dernier message: 08/02/2009, 09h32
  5. Réponses: 7
    Dernier message: 19/04/2008, 17h44

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