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 :

Sémantique de mouvement & style de codage


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut Sémantique de mouvement & style de codage
    Hello,

    Soit la fonction suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void maFonction(std::vector<int>& monVecteur)
    {
        // vaut-il mieux :
        monVecteur.resize(10000);
        // ou
        monVecteur = std::vector<int>(10000);
    }
    J'aurais tendance à utiliser la première forme, mais étant tombé sur la deuxième forme dans le code d'un collègue, j'aurais un peu de mal à argumenter (on va juste réallouer les quelques octets des "métadonnées" du vecteur).

  2. #2
    Membre Expert
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Par défaut
    Hello,

    Il faut voir l'état actuel du vecteur, la deuxième solution évite d'avoir un vecteur trop grand (mémoire réservée). Mais en dehors de ce cas un peu particulier je préférerais la première forme aussi.

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    À l'entrée de la fonction, le vecteur est vide (c'est une valeur de retour).

  4. #4
    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,
    Citation Envoyé par oodini Voir le message
    À l'entrée de la fonction, le vecteur est vide (c'est une valeur de retour).
    Heuu... en est tu vraiment sur et certain

    Si oui (ou si tu considère que cela doit forcément être le cas), il serait intéressant d'expliciter cette précondition par une assertion car, si ce n'est pas le cas, c'est que tu es face à une erreur de la part de l'utilisateur de la fonction.

    Si non (ou si on ne considère pas que c'est forcément le cas), tu ne peux simplement pas partir du principe que ce sera le cas...
    Citation Envoyé par Iradrille Voir le message
    Hello,

    Il faut voir l'état actuel du vecteur, la deuxième solution évite d'avoir un vecteur trop grand (mémoire réservée). Mais en dehors de ce cas un peu particulier je préférerais la première forme aussi.
    A vrai dire, tab.resize(N) et tab = std::vector<int>(N) auront tous les deux le même résultat :définir la taille du tableau à la valeur indiquée...

    Ce qui ne ferait que modifier la capacité (comprend : le nombre d'élément maximum avant de devoir redemander de l'espace supplémentaire), ce serait le code tab.reserve(N).

    Dés lors, en dehors de toute certitude que le tableau est bel et bien vide -- et j'irais même jusqu'à dire "et même si le contrat selon lequel le tableau doit être vide était explicitement vérifié" -- je pencherais de préférence pour l'utilisation de resize(), simplement parce que:
    1. cela évite de perdre plus de données que nécessaire dans la bataille au cas où le tableau n'est pas vide
    2. j'estime qu'il ne sert à rien de passer par une variable temporaire alors que la classe fournit "tout ce qu'il faut" pour obtenir un résultat similaire

    Alors, bien sur, il y a le fameux argument "oui, mais grace à la sémantique de mouvement, cela revient malgré tout au même", il faut savoir que, même si la sémantique de mouvement permet d'aller beaucoup plus vite que la copie "normale", elle implique quand même toujours la "canibalisation" de la variable temporaire et que cette "canibalisation" (en fait, un std::swap sur l'ensemble des membres de la classe, à peu de chose près ) prendra de toutes façons plus de temps que de redéfinir "tout simplement" les bonnes valeurs pour la variable qui existe déjà...

    Bien sur, on parle de "quelques fréquences d'horloge en plus ou en moins", mais... elles seront bel et bien utilisées
    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

  5. #5
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    En fait tes 2 écritures sont identiques dans le résultat.
    Dans le 2° cas, tu crées un temporaire puis utilises l'opérateur =, possiblement optimisé par le compilo.
    Mais la 1° écriture est préférable dans tous les cas.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  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
    Citation Envoyé par Bousk Voir le message
    En fait tes 2 écritures sont identiques dans le résultat.
    Dans le 2° cas, tu crées un temporaire puis utilises l'opérateur =, possiblement optimisé par le compilo.
    Mais la 1° écriture est préférable dans tous les cas.
    Merci de confirmer ce que j'ai écrit
    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
    Membre Expert
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Par défaut
    Citation Envoyé par koala01 Voir le message
    A vrai dire, tab.resize(N) et tab = std::vector<int>(N) auront tous les deux le même résultat :définir la taille du tableau à la valeur indiquée...

    Ce qui ne ferait que modifier la capacité (comprend : le nombre d'élément maximum avant de devoir redemander de l'espace supplémentaire), ce serait le code tab.reserve(N).
    tab.resize(N); ne va pas réduire la mémoire réservée au vecteur (faudra un shrink_to_fit).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void maFonction(std::vector<int>& monVecteur)
    {
        monVecteur.resize(10000); // si monVecteur.capacity() > 10000 alors on garde un vecteur "trop grand"
        // "un peu trop grand" -> osef, "beaucoup trop grand" -> ça peut être problématique
        // -> mémoire réservée au vecteur pas libérée pour le moment
    }
    C'est généralement pas un problème (et ici le vecteur est vide en entrée), mais ça peut l'être.

  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
    Citation Envoyé par Iradrille Voir le message
    tab.resize(N); ne va pas réduire la mémoire réservée au vecteur (faudra un shrink_to_fit).
    Je ne suis pas sur, mais il me semble que c'est implementation defined (en tout cas, ca l'est pour std::string )... j'irai vérifier dans la norme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void maFonction(std::vector<int>& monVecteur)
    {
        monVecteur.resize(10000); // si monVecteur.capacity() > 10000 alors on garde un vecteur "trop grand"
        // "un peu trop grand" -> osef, "beaucoup trop grand" -> ça peut être problématique
        // -> mémoire réservée au vecteur pas libérée pour le moment
    }
    C'est généralement pas un problème (et ici le vecteur est vide en entrée), mais ça peut l'être.
    Ben, que le tableau soit vide en entrée ou non, il est clair que celui qui décide d'effectuer un resize (ou un reserve, d'ailleurs) basé sur un nombre magique prend énormément de risques : si son nombre magique est "très près" du nombre final d'éléments, tout va bien; mais, plus il s'en écarte, plus il prend le risque soit d'avoir prévu (beaucoup) trop d'espace, soit de n'avoir limité "qu'un tout petit peu" le nombre d'augmentation de taille qui seront effectués

    Car il faut bien dire que le problème de la taille n'est pas uniquement limité au fait que la taille soit... trop importante
    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

Discussions similaires

  1. Réponses: 112
    Dernier message: 22/10/2013, 20h20
  2. Réponses: 1
    Dernier message: 14/05/2012, 18h54
  3. [GNU Emacs] un style de codage java correct
    Par zafo dans le forum Autres Logiciels
    Réponses: 0
    Dernier message: 23/10/2007, 15h05
  4. [POO] Question de style et méthode de codage
    Par elitemedia dans le forum Langage
    Réponses: 1
    Dernier message: 23/12/2006, 22h03

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