2009-09-07 8 views
6

Meine Anwendung verwendet eine große Menge von Panda Objekte. Jede Panda hat eine Liste von Bamboo Objekten. Diese Liste ändert sich nicht, wenn die Panda initialisiert ist (keine Bamboo Objekte hinzugefügt oder entfernt). Derzeit ist meine Klasse wie folgt umgesetzt:Objekte mit variabler Länge: Immer eine gute Idee?

class Panda 
{ 
    int a; 
    int b; 
    int _bambooCount; 
    Bamboo* _bamboo; 

    Panda (int count, Bamboo* bamboo) 
    { 
    _bambooCount = count; 
    _bamboo = new Bamboo[count]; 

    // ... copy bamboo into the array ... 
    } 
} 

Um den Aufwand für die Zuteilung einer Reihe von Bamboo Objekte zu lindern, konnte ich diese Klasse wie folgt implementieren - grundsätzlich anstelle von Objekten über den regulären Konstruktor erstellen, eine Konstruktion Verfahren ordnet ein einziger Speicherblock sowohl das Panda Objekt und seine Bamboo Array zu halten:

class Panda 
{ 
    int a; 
    int b; 

    Panda() 
    { 
     // ... other initializations here ... 
    } 

    static Panda *createPanda (int count, Bamboo* bamboo) 
    { 
    byte* p = new byte[sizeof(Panda) + 
     sizeof(Bamboo) * count]; 
    new (p) Panda(); 

    Bamboo* bamboo = (Bamboo*) 
     p + sizeof(Panda); 

    // ... copy bamboo objects into the memory 
     // behind the object... 

     return (Panda*)p; 
    } 
} 

Sie Probleme mit dem zweiten Entwurf, außer dem erhöhten Wartungsaufwand voraussehen können? Ist das ein akzeptables Designmuster oder einfach eine vorzeitige Optimierung, die mich später wieder beißen könnte?

+0

Es wird beißen. Und es wird hart beißen. –

+1

Sie brechen die meisten Semantiken für Klassen in C++. Objekte mit variabler Länge sind in C++ nicht vorhanden. – jalf

+2

Wenn Sie an solchen Hacks interessiert sind, können Sie sich auch die Klassenvorlagen TBuf8 und TBuf16 von Symbian/C++ anschauen. –

Antwort

9

C++ gibt Ihnen eine andere Option. Sie sollten std :: vector verwenden.

class Panda 
{ 
    int a; 
    int b; 
    std::vector<Bamboo> bamboo; 
    // if you do not want to store by value: 
    //std::vector< shared_ptr<Bamboo> > bamboo; 

    Panda (int count, Bamboo* bamb) : bamboo(bamb, bamb+count) {} 
} 

Wenn Sie Panda und Bambusse im Dauerspeicher speichern möchten Sie Lösung von this article nutzen könnten. Die Grundidee besteht darin, operator new und operator delete zu überlasten.

+0

Sie müssen sich der Nebenwirkungen dieser Art von Lösungen und der Probleme bewusst sein, mit denen Sie zu tun haben: Benutzer werden nicht in der Lage sein, die Objekte in Containern zu verwenden (insbesondere std :: vector, die den Speicher basierend auf der Größe von vorlistet) der Typ, der übergeben wird) Diese Trickserei wird mit Code enden, der nicht nur schwer zu warten ist (der Fragesteller weiß), sondern auch unnatürlich zu verwenden. –

+0

Am natürlichsten ist es, 'std :: vector' zu verwenden. Alle anderen Lösungen sind sehr eingeschränkt verwendbar und sollten mit Vorsicht angewendet werden. –

+0

Wenn ich mich nicht irre, verwendet die String-Implementierung von GCC diese Art von Trickserei. Der Trick besteht darin, dass das Panda-Objekt einen einzelnen Zeiger auf die (übergeordnete) Implementierungsklasse enthält. – UncleBens

1

Sie verwenden "neues" Aussehen des neuen Betreibers. Es ist völlig richtig, relativ Panda, aber warum verwenden Sie nicht Bamboo Initialisierer?

4

Sie werden gebissen, wenn jemand einen Panda nach Wert nimmt, z.

//compiler allocates 16-bytes on the stack for this local variable 
Panda panda = *createPanda(15, bamboo); 

Es kann akzeptabel sein (ist aber sehr wahrscheinlich eine vorzeitige und schreckliche Optimierung), wenn Sie sich immer nur auf den Dinge durch Zeiger verweisen und nie von Wert, und wenn Sie den Copy-Konstruktor und Zuweisungsoperator in Acht nehmen.

3

Basierend auf meiner Erfahrung ist eine vorzeitige Optimierung meistens immer "verfrüht". Das heißt, Sie sollten Ihren Code profilieren und feststellen, ob Optimierungsbedarf besteht oder ob Sie nur mehr Arbeit für sich selbst schaffen auf lange Sicht.

Auch scheint mir die Frage, ob die Optimierung es wert ist oder nicht, sehr von der Größe der Bamboo-Klasse und der durchschnittlichen Anzahl von Bamboo-Objekten pro Panda abhängig zu sein.

3

Dies wurde in C.
gefunden Aber in C++ gibt es keinen wirklichen Bedarf.

Die eigentliche Frage ist, warum willst du das tun?

Dies ist eine vorzeitige Optimierung, verwenden Sie einfach ein std :: vector <> intern und alle Ihre Probleme werden verschwinden.

Weil Sie ein RAW-Zeiger intern verwenden, dass die Klasse besitzt würden Sie die Standardversionen außer Kraft setzen müssen:

  • Standardkonstruktor
  • Destructor
  • Copykonstruktor
  • Zuweisungsoperator
7

Wie überzeugen wir Menschen, dass in der Programmierung Einfachheit und Klarheit - kurz: Was Mathematiker "Eleganz" nennen - ist kein überflüssiger Luxus, sondern eine entscheidende Frage, die zwischen Erfolg und Misserfolg entscheidet?

- Edsger W. Dijkstra

+0

Nur nicht. Viele Dinge können schiefgehen ... Wie werden Sie Kopierkonstruktoren, Aufgaben, Destruktoren implementieren? Wie gehen Sie mit Benutzern um, die Arrays von Panda haben wollen? –

+0

Mathematiker haben keine Ahnung von Programmierung und der realen Welt. – Lothar

2

Wenn Sie so verzweifelt, werden Sie wahrscheinlich so etwas tun kann:

template<std::size_t N> 
class Panda_with_bamboo : public Panda_without_bamboo 
{ 
    int a; 
    int b; 
    Bamboo bamboo[N]; 
} 

Aber ich glaube, dass Sie nicht verzweifelt sind, dann aber vorzeitig zu optimieren.

Verwandte Themen