Frage

Ich habe eine leichte Templat Klasse bekommt, die ein paar Mitglied Objekte enthalten, die nur sehr selten verwendet werden, und so würde Ich mag ihre Konstruktoren und Destruktoren außer in den seltenen Fällen zu vermeiden, rufen, wenn ich sich tatsächlich nutzen.

Um das zu tun, ich "declare", um sie in meiner Klasse wie folgt aus:

template <class K, class V> class MyClass
{
public:
   MyClass() : wereConstructorsCalled(false) {/* empty */}
   ~MyClass() {if (wereConstructorsCalled) MyCallPlacementDestructorsFunc();}

   [...]

private:
   bool wereConstructorsCalled;
   mutable char keyBuf[sizeof(K)];
   mutable char valBuf[sizeof(V)];
};

... und dann verwende ich die Platzierung neuer und Platzierung löschen einzurichten und abzureißen die nur Objekte, wenn ich brauche eigentlich so zu tun.

die C ++ FAQ lesen, sagte er, dass, wenn die Platzierung neuer verwenden, muss ich vorsichtig sein, dass die Platzierung richtig ausgerichtet ist, oder ich würde in Schwierigkeiten geraten.

Meine Frage ist, werden die keyBuf und valBuf Arrays in allen Fällen richtig ausgerichtet werden, oder gibt es einen zusätzlichen Schritt, den ich nehmen müssen, um sicherzustellen, dass sie richtig ausgerichtet werden? (Wenn ja, ein nicht-plattformabhängigen Schritt wäre vorzuziehen)

War es hilfreich?

Lösung

Es gibt keine Garantie, dass Sie die entsprechende Ausrichtung zu bekommen. Arrays sind im Allgemeinen nur für den Elementtyp ausgerichtet werden garantiert. Ein char Array wird für die Speicherung von char ausgerichtet sind.

Die einzige Ausnahme ist, dass char und unsigned char Arrays mit new zugeordnet sind maximale Ausrichtung gegeben, so dass Sie beliebige Typen in sie speichern können. Aber diese Garantie nicht in Ihrem Fall anwenden, wie Sie Heapzuordnung sind zu vermeiden.

TR1 und C ++ 0x einige sehr hilfreiche Typen hinzufügen aber:

std::alignment_of und std::aligned_storage zusammen geben Ihnen eine tragbare (und funktionierende) Antwort.

std::alignment_of<T>::value gibt Ihnen die Ausrichtung für einen Typ T erforderlich. std::aligned_storage<A, S>::type gibt Ihnen einen POD-Typ mit Ausrichtung A und Größe S. Das bedeutet, dass Sie sicher Ihr Objekt in eine Variable vom Typ std::aligned_storage<A, S>::type schreiben können.

(In TR1, der Namensraum ist std::tr1, anstatt nur std)

Andere Tipps

Darf ich fragen, warum Sie sie in einen char buffer platzieren möchten? Warum nicht einfach erstellen Zeiger Objekte von K und V dann instanziiert, wenn Sie es brauchen.

Vielleicht habe ich Ihre Frage nicht verstehen, kann aber nicht einfach char *keyBuf[..size..]; tun, setzen sie zunächst auf NULL (nicht zuordenbar) und ordnen sie das erste Mal, wenn Sie es brauchen?

Was Sie versuchen, mit der Platzierung zu tun neu scheint riskant und schlechten Codierung Stil.

Wie auch immer, Code Ausrichtung ist die Umsetzung abhängig.

Wenn Sie ändern möchten Code Ausrichtung Verwendung Pragma Pack

#pragma pack(push,x)

// class code here

#pragma pack(pop) // to restore original pack value

Wenn x 1 ist, wird es keine Polsterung zwischen Elementen sein.

Hier ist ein Link zu lesen

http://www.cplusplus.com/forum/general/14659/

Ich fand diese Antwort von SiCrane geschrieben unter http: // www ? .gamedev.net / community / Foren / topic.asp topic_id = 455.233 :

  

Doch für statische Zuordnungen, es ist weniger verschwenderisch um den Speicherblock in einer Union mit anderen Arten zu erklären. Dann wird der Speicherblock gewährleistet werden, um die Ausrichtung des restriktivsten Typs in der Union ausgerichtet werden. Es ist immer noch ziemlich hässlich oder so.

klingt wie eine Vereinigung könnte den Trick tun!

Ich empfehle, dass Sie bei der boost::optional Vorlage aussehen. Es tut, was Sie brauchen, auch wenn Sie es nicht wahrscheinlich bei deren Umsetzung aussehen können Sie sollten.

Es nutzt alignment_of und type_with_alignment für seine Ausrichtung Berechnungen und Garantien.

Um eine sehr sehr lange Geschichte zu machen sehr sehr kurz dies wird nicht jedem Ihre Leistung helfen und verursacht eine Menge Kopfschmerzen und es wird nicht lange dauern, bis Sie gelutscht in Ihre eigenen Speicher managemer zu schreiben.

Placement neu ist in Ordnung für einen POD (aber nicht speichern Sie nichts), aber wenn Sie einen Konstruktor überhaupt haben, dann wird es nicht zur Arbeit überhaupt geht.

Sie können auch hängen nicht von dem Wert Ihrer boolean Variable, wenn Sie neue Platzierung verwenden.

Placement neue hat Verwendungen, aber nicht wirklich für diese.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top