6
votes

Puis-je utiliser l'opérateur [] en C ++ pour créer des tableaux virtuels

J'ai une base de code importante, à l'origine C porté à C ++ il y a de nombreuses années, qui fonctionne sur un certain nombre de grandes matrices de données spatiales. Ces tableaux contiennent des structures représentant des entités de point et de triangle représentant des modèles de surface. J'ai besoin de refactoriser le code de telle sorte que la manière dont ces entités soient stockées varie en interne varie en interne pour des scénarios spécifiques. Par exemple, si les points se trouvent sur une grille plate régulière, je n'ai pas besoin de stocker les coordonnées X et Y, car ils peuvent être calculés à la volée, comme cela peut les triangles. De même, je souhaite profiter des outils de base tels que STXXL pour stockage. Le moyen le plus simple de le faire consiste à remplacer l'accès au tableau avec des fonctions de type et d'obtention de type, par exemple

point[a].z = point[b].z + point[c].z


0 commentaires

4 Réponses :


5
votes

Vous n'avez pas besoin de passer la matrice par valeur. Pour la mutation des valeurs de la matrice, vous voulez deux versions de opérateur [] , qui renvoie une référence (à la mutate) et une référence Const.

Il n'y a aucune raison de principe de ne pas utiliser opérateur [] , tant que vous n'avez pas besoin de modifier le type de stockage au moment de l'exécution - il n'y a pas d'opérateurs virtuels, de sorte que vous le feriez. Besoin d'une fonction nommée si vous souhaitez polymorphisme d'exécution. Dans ce cas, vous pouvez créer un simple struct qui adapte les appels de l'opérateur aux appels de fonction (bien qu'il dépend plutôt de l'API de stockage - si le code suppose que l'attribution aux variables de membre du point change les données stockées. , vous devrez peut-être apporter le point de taper une variable de modèle aussi pour que cela puisse être remplacé).

Regardant votre code d'échantillon, il a un test de stratégie de stockage. Ne faites pas cela. Utilisez OO et demandez à votre objet de stockage implémenter une interface virtuelle commune, ou (probablement mieux) utilisez la programmation de modèle pour faire varier le mécanisme de stockage.

Si vous regardez les garanties fabriquées par std :: vecteur (dans des normes C ++ plus récentes), il est possible d'avoir quelque chose qui a un stockage dynamique et permet une utilisation de l'arithmétique du pointeur, bien que cela nécessite un stockage contigu. Étant donné que certaines de vos valeurs sont créées à la volée, il ne vaut probablement pas la peine de placer cette restriction sur vos implémentations, mais la contrainte elle-même n'empêche pas l'utilisation de opérateur [] .


2 commentaires

Le retour d'une référence au point implique d'avoir plusieurs points uniques pour toutes les références potentiellement en direct actives en même temps. Cela nécessitera une cache de données transformées, mais devrait être fonctionnel. Merci d'avoir répondu.


Utilisation du WRT d'une stratégie de stockage plutôt que de OO ou de modèles, cela ne fonctionnerait pas car le code existant n'est pas écrit pour le soutenir et une exigence principale est de minimiser la quantité de réécriture. Je veux laisser tomber quelque chose qui est polymorphe polymorphe à l'arrière, mais à l'extrémité frontale imite une matrice C. Si je l'écrivais à partir de zéro, les modèles sont sans aucun doute la voie à suivre.



2
votes

Ce que vous voulez est possible, mais comme vous avez besoin d'un accès en écriture également, le résultat sera parfois un peu plus complexe. Ce que vous voulez, c'est la fonction Setter renvoyant non pas un "accès en écriture de points", plutôt une copie temporaire, qui fera l'écriture une fois que la copie sort de la portée.

Le fragment de code suivant tente de décrire la solution: P>

class PointVector
{
  MyClass container_;

  public:
  class PointExSet: public Point
  {
    MyClass &container_;
    int index_;

    public:
    PointExSet(MyClass &container, int index)
      :Point(container.GetVector(index)),container_(container),index_(index)
    {
    }

    ~PointExSet()
    {
      container_.PutVector(index_) = *this;
    }
  };

  PointExSet operator [] (int i)
  {
    return PointExSet(container_,i);
  }
};


1 commentaires

Yup, d'où la nécessité de références. Je pense que je devrais pouvoir le faire en utilisant une cache du type transformé, avec un index de la même taille que le tableau utilisé pour maintenir le cache.



1
votes

Pour avoir un contrôle total sur les opérations sur le tableau, l'opérateur [] doit renvoyer un objet spécial (inventé il y a longtemps et appelé "curseur") qui gérera les opérations pour vous. À titre d'exemple: xxx


0 commentaires

0
votes

Après avoir lu les réponses ci-dessus, j'ai décidé que la réponse de Pete avec deux versions de opérateur [] était la meilleure voie à suivre. Pour gérer le morphing entre les types au moment de l'exécution, j'ai créé une nouvelle classe de modèles de tableau qui a pris quatre paramètres comme suit; xxx

Le stockage de données principale est dans m_basedata qui Est-ce que les données de son format natif, qui peuvent varier en type comme indiqué. m_refcache est une matrice secondaire au cache des éléments dans le format attendu, et la fonction getcachedelement utilise les fonctions virtuelles convertissez pour traduire les données telles que c'est déplacé dans et hors du cache. Le cache doit être au moins aussi gros que le nombre de références simultanées pouvant être actives à une fois, mais dans mon cas bénéficiera probablement d'être plus grande, car elle réduit le nombre de conversions requises. Alors que la mise en œuvre du curseur d'ALSK aurait probablement bien fonctionné, la solution donnée nécessite moins de copies d'objet et de variables temporaires, et devrait donner une légère meilleure performance qui est importante dans ce cas.

excuses à tous vos fans de tous vos fans l'aperçu des MFC plus âgés; Le reste du projet est MFC, il a donc plus de sens dans ce cas. Le cbigarray était le résultat d'un question de dépassement de pile associée qui est devenue la base de ma grande manipulation de la matrice. J'espère terminer la mise en œuvre aujourd'hui et tester demain. Si tout va du ventre sur moi, je modifierai ce post avec précision.


0 commentaires