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 :

reinterpret_cast de collection de pointeur


Sujet :

Langage C++

  1. #1
    Membre averti Avatar de vikki
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    292
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Mai 2007
    Messages : 292
    Points : 302
    Points
    302
    Par défaut reinterpret_cast de collection de pointeur
    Bonjour à tous,

    Je me demandais s'il était légal (dans le sens ayant un comportement prédictif) de caster brutalement un std::vector de pointeur vers un std::vector d'un autre type de pointeur.

    Concrètement cela donne:

    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
    struct test {
       int var;
    };
     
    std::vector<void*> collection;
     
    /*
    .
    .
    fill collection
    .
    .
    */
     
    std::vector<test*> res = *reinterpret_cast< const std::vector<test*> * >(&collection);
    On suppose dans ce cas que les pointeurs dans 'collection' pointent tous bien vers des instances de type 'test'. Cela fonctionne parfaitement sous Visual et semble d'ailleurs deux fois plus rapide qu'une copie via boucle for. Par contre, cela ressemble furieusement à une bombe à retardement prête à me sauter à la tête.

    Je n'arrive pas à trouver une réponse claire sur le net à part que cette méthode est moche et à éviter.

  2. #2
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 965
    Points
    32 965
    Billets dans le blog
    4
    Par défaut
    Bonjour,

    je pense que c'est au mieux dangeureux.
    vector est un type complexe, caster chaque élément est à la limite explicable, mais le vector entier pas vraiment.
    Si vraiment je devais réaliser un tel cast, je le casterais probablement vers un tableau et non un vector:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    test** = reinterpret_cast<test**>(&(vec[0]));
    Pour passer d'un élément à l'autre, un peu d'arithmétique des pointeurs.
    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.

  3. #3
    Membre averti Avatar de vikki
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    292
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Mai 2007
    Messages : 292
    Points : 302
    Points
    302
    Par défaut
    C'est certain que cela semble douteux. Cependant, si la class vector n'est pas spécialisée pour les pointeurs considérés, j'ai du mal à voir où est le danger (à part pour les cast entre pointeurs eux mêmes en cas d’héritage multiple).

  4. #4
    Membre expert

    Avatar de germinolegrand
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Octobre 2010
    Messages
    738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Octobre 2010
    Messages : 738
    Points : 3 892
    Points
    3 892
    Par défaut
    Si tu veux copier le tableau, je te conseille memcpy.
    C++03 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    std::vector<void*> first;
     
    std::vector<T*> sec(first.size());
    memcpy(&sec[0], &first[0], first.size()*sizeof(void*));
    C++11 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    std::vector<void*> first;
     
    std::vector<T*> sec;
    sec.resize(first.size());
    memcpy(sec.data(), first.data(), first.size()*sizeof(void*));

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Salut,

    Pour répondre à la première question, oui, c'est légal dans le sens où c'est l'utilisation pour laquelle est prévue reinterpret_cast.

    Il faut cependant bien comprendre ce que fait reinterpret_cast pour être sur de ne pas risquer de "tout faire pêter" :

    En effet, cela a un comportement tout à fait similaire au cast "C style" brutal et barbare, dans le sens où cela indique au compilateur quelque chose comme
    Je sais que tu connais telle donnée comme étant de tel type, mais je te demande de me faire confiance et de la considérer comme s'il s'agissait de tel autre type
    Le compilateur va donc te faire une confiance aveugle et considérer la variable comme étant du type que tu lui a indiqué, sans se poser la moindre question

    Comme tu l'as toi même si bien fait remarquer, cela revient à armer une bombe à retardement car, si tu te trompes de type, il est très difficile de prévoir le résultat que tu obtiendras

    De plus, il faut se méfier avec la classe std::vector dans le sens où elle maintient le nombre d'éléments qu'elle contient ainsi que le nombre d'éléments au delà duquel elle devra agrandir la taille du tableau.

    Le réinterpret_cast ne va en aucun cas forcer la classe vector à recalculer ces valeurs pour les adapter à la nouvelle taille des éléments.

    Tu risques donc de tenter d'accéder à des éléments "hors limites" si tu transtype ton vector d'un type en un vector d'un type de taille supérieure (par exemple, un std::vector<int> en std::vector<double>).

    Par chance, la taille d'un pointeur est clairement définie pour un compilateur donné sur une architecture donnée, et tu retardes donc ce risque si tu travailles sur un std::vector qui manipule des pointeurs au moment où tu essayeras d'accéder à l'élément pointé par le pointeur (car sizeof(int) est différent de sizeof(double)), dans le sens où le tableau sous jascent de std::vector gardera la même taille qu'il s'agisse de pointeurs sur void, sur int ou sur double.

    Bref, tu l'auras compris: la méthode est légale, mais très moche et à éviter autant que faire se peut

    De prime abord, je te conseillerais de limiter l'utilisation de cette technique aux cas où tu n'as vraiment pas le choix: lorsqu'il s'agit, par exemple, de t'interfacer avec une fonction C qui prend un pointeur de pointeurs sur void ou cas similaires

    Tu utiliserais alors sans doute quelque chose comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    laFonctionC(reinterpret_cast<void**>(&myVector[0]);
    Dans tous les autres cas, tu as franchement largement intérêt à utiliser ton vector comme ce qu'il est: une collection d'objet d'un type clairement défini
    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: 2
    Dernier message: 10/03/2011, 00h44
  2. [VB6] Modifier la clé d'un élément d'une collection
    Par Ricou13 dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 21/11/2002, 14h49
  3. [Turbo Pascal] Allocation et désallocation de pointeurs dans une fonction
    Par neird dans le forum Turbo Pascal
    Réponses: 13
    Dernier message: 17/11/2002, 20h14
  4. djgpp et pointeurs far -2
    Par elvivo dans le forum Autres éditeurs
    Réponses: 16
    Dernier message: 29/07/2002, 22h43
  5. djgpp et pointeurs far
    Par elvivo dans le forum C
    Réponses: 2
    Dernier message: 13/07/2002, 00h44

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