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

Langage C++ Discussion :

Initialisation d'un tableau avec constructeurs


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2007
    Messages
    373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Santé

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Par défaut Initialisation d'un tableau avec constructeurs
    Bonjour,

    Je cherche a initialiser un simple tableau de données non copiables et sans constructeur par défaut. Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    struct test {
        test(int i) {}
        test(const test&) = delete;
    };
     
    int main() {
        test tbl[4] {1, 2, 3, 4};
        return 0;
    }
    Le compilateur (g++) me dit :
    Citation Envoyé par g++
    error: use of deleted function test::test(const test&)
    Il semble donc créer une instance de test pour chaque élément de la liste d'initialisation, puis tente de les copier dans le tableau.

    Connaissez-vous un moyen d'éviter cette copie inutile ? Mes recherches sur la toile ont été infructueuses...

    NB :
    • Je peux utiliser le C++11.
    • Je pourrais bien sûr passer par un tableau de pointeurs (nus ou intelligents), mais je trouve ça dommage pour une raison aussi bête...

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    118
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 118
    Par défaut
    Je cite http://en.cppreference.com/w/cpp/lan...initialization :
    The effects of aggregate initialization are:
    Each array element or non-static class member, in order of array subscript/appearance in the class definition, is copy-initialized from the corresponding clause of the initializer list.

  3. #3
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    éventuellement, avec std::array, mais sinon, tu ne peux pas faire un tableau si tu n'as ni copie ni valeur par défaut.

  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    118
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 118
    Par défaut
    std::array est un aggregat donc aggregate-initialized.

  5. #5
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    Bonjour

    vector + emplace (ou emplace_back) : http://en.cppreference.com/w/cpp/con...vector/emplace

    Mais je sens l'anguille sous roche

  6. #6
    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,

    Déjà, si tu crées une structure non copiable, c'est sans doute parce que ta structure a sémantique d'entité, et donc, qu'elle risque de servir de base à une classe dérivée. (les classes / structures ayant sémantique de valeur sont classiquement copiables )

    Dans cette hypothèse, il est donc cohérent de travailler avec des pointeurs, pour profiter entre autres du polymorphisme

    Ce n'est pas parce que tu n'envisages pas pour l'instant de faire dériver une classe de ta classe actuelle que tu n'en éprouveras pas le besoin par la suite, donc, autant prendre les devants, non

    A moins, bien sur, que ta classe actuelle ait sémantique d'entité, et, dans ce cas, il est utile de se rappeller la règle des trois grands :

    Si tu fournit une implémentation personnelle de l'une des fonctions de base que sont le constructeur de copie, l'opérateur d'affectation ou le destructeur, tu dois fournir une implémentation personnelle pour les deux autres

    Dans cette hypothèse, je présume (peut etre à tord) que si tu as décidé de rendre ta classe non copiable, c'est parce qu'elle contient un pointeur pour lequel tu effectues une allocation dynamique de la mémoire, et que tu effectues donc un delete dans ton destructeur.

    Cela pourrait justifier le fait que tu veuilles éviter la copie (mais il faudrait d'ailleurs aussi éviter l'affectation, vu que c'est le même combat ) sauf que, si ta classe a sémantique de valeur, il n'y a pas grand chose à faire : ta classe doit etre copiable et affectable

    L'idée pour arriver à ce résultat est
    1. De faire une copie en profondeur du pointeur dans le constructeur de copie
    2. De passer par un idiôme "copy and swap" dans l'opérateur d'affectation
    (un tour du coté de la FAQ devrait te fournir les informations relatives à ces concepts )

    Sinon, si ta classe a réellement sémantique d'entité et que tu es sur qu'elle ne sera jamais dérivée (mais peux tu vraiment avoir cette certitude ), tu peux toujours te tourner vers la sémantique de mouvement, vu que tu travailles en C++11

    Mais un tableau statique d'élément ne fonctionnera pas, car, pour pouvoir créer un tableau statique, il faut pouvoir initialiser chacun des membres, à moins de recourir à un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Test tab[4]={std::move(Test(1)),
                 std::move(Test(2)),
                 std::move(Test(3)),
                 std::move(Test(4)) };
    (Et encore, je ne l'ai pas testé )
    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

  7. #7
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    Sinon, si ta classe a réellement sémantique d'entité et que tu es sur qu'elle ne sera jamais dérivée (mais peux tu vraiment avoir cette certitude ), tu peux toujours te tourner vers la sémantique de mouvement, vu que tu travailles en C++11
    Attention, la sémantique de mouvement fait une copie quand c'est pas possible de déplacer. En l’occurrence, pour un tableau dont les données sont contiguës (et donc on n'a pas le chois de la localisation des données en mémoire après insertion), les données sont forcement copiées.

    Concernant la copie avec les valeurs, dans l'absolue c'est vraie. Mais lorsque l'on a des gros tableaux de données à charger pour faire des calculs, s'amuser à copier les données fait toujours un peu mal
    Dans ce cas, ça me parait pas incohérent de forcer l'interdiction de la copie, même si cela ne respecte pas la sémantique de valeur.
    A mon avis, la seule chose importante est de respecter la sémantique de valeur au niveau du tableau complet et non de chaque élément

    Mais il faut voir exactement où se trouve le problème de perte de performance par copie. J'ai du mal à imaginer qu'un tableau statique sur la pile créé à l'initialisation puisse poser des problèmes de performances.

    EDIT :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Test tab[4]={std::move(Test(1)),
                 std::move(Test(2)),
                 std::move(Test(3)),
                 std::move(Test(4)) };
    move sert à rien ici, ce sont déjà des temporaires, donc des rvalues. move sert à convertir une lvalue en rvalue, donc est utile que sur les variables (move ne fait rien sur un temporaire) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Test t1 = Test(1);
    Test t2 = Test(2);
    Test t3 = Test(3);
    Test t4 = Test(4);
    Test tab[4]={ std::move(t1), std::move(t2), std::move(t3), std::move(t4) };

Discussions similaires

  1. initialisation d'un tableau avec le constructeur
    Par petaf dans le forum Langage
    Réponses: 5
    Dernier message: 02/06/2014, 09h34
  2. Réponses: 0
    Dernier message: 10/05/2012, 08h33
  3. Initialisation statique d'objet avec constructeur
    Par Captain'Flam dans le forum Débuter
    Réponses: 11
    Dernier message: 07/09/2011, 16h42
  4. Réponses: 7
    Dernier message: 29/01/2009, 12h32
  5. Initialiser tableau class constructeur
    Par dédé dans le forum C++
    Réponses: 3
    Dernier message: 21/11/2006, 13h43

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