2010-09-13 7 views
5

Ich entwickle einen Motor für vorhandenen Code auf eine andere Plattform zu portieren. Der vorhandene Code wurde mithilfe einer API von Drittanbietern entwickelt, und meine Engine wird diese API-Funktionen von Drittanbietern im Hinblick auf meine neue Plattform neu definieren.Soll ich einen Iterator oder einen Zeiger auf ein Element in einem STL-Container zurückgeben?

Die folgenden Definitionen stammen aus der API:

typedef unsigned long shape_handle;  
shape_handle make_new_shape(int type); 

Ich brauche make_new_shape neu zu definieren, und ich habe die Möglichkeit, shape_handle neu zu definieren.

Ich habe diese Struktur (vereinfacht) definiert:

struct Shape 
{ 
    int type 
}; 

Die Caller von make_new_shape nicht über die zugrunde liegende Struktur der Shape schert, es braucht nur ein „Griff“, um es so, dass es Funktionen aufrufen wie:

void `set_shape_color(myshape, RED);` 

wo myshape ist der Griff zur Form.

Meine Engine verwaltet den Speicher für die Shape Objekte und andere Anforderungen diktieren, dass die Engine Shape Objekte in einer Liste oder anderen iterierbaren Container speichern soll.

Meine Frage ist, was ist der sicherste Weg, dieses Handle darzustellen - wenn der Shape selbst in einer std :: list gespeichert wird - ein Iterator, ein Zeiger, ein Index?

+2

Warum haben Sie std :: list gewählt? –

+0

@jk - Ich muss 'Shape' Objekte aus der Mitte des Containers hinzufügen und entfernen können. – BeeBand

+0

Sie möchten definitiv shape_handle (oder make_new_shape) nicht neu definieren. –

Antwort

3

Die Antwort hängt von Ihrer Darstellung:

  • für std::list, verwenden Sie einen iterator (keinen Zeiger), weil ein iterator ermöglicht es Ihnen, das Element zu entfernen, ohne die ganze Liste zu Fuß.
  • für std::map oder boost::unordered_map, verwenden Sie die Key (natürlich)

Ihr Entwurf viel stark sein würde, wenn Sie einen assoziativen Container verwendet, weil assoziative Container Ihnen die Möglichkeit, auf das Vorhandensein des Objekts abzufragen, anstatt Undefined Behavior aufzurufen.

Versuchen sowohl map und unordered_map Benchmarking zu sehen, die man schneller in Ihrem Fall ist :)

6

sowohl ein Iteratoren oder ein Zeiger wird schlechte Sachen tun, wenn Sie versuchen, auf sie zuzugreifen, nachdem das Objekt gelöscht wurde, so weder intrinsisch sicherer ist. Der Vorteil eines Iterators besteht darin, dass er für den Zugriff auf andere Mitglieder Ihrer Sammlung verwendet werden kann.

Also, wenn Sie nur Ihre Form zugreifen möchten, dann wird ein Zeiger einfachste werden. Wenn Sie Ihre Liste durchlaufen möchten, verwenden Sie einen Iterator.

Ein Index ist in einer Liste seit std :: Liste nutzlos ist die Überlastung von dem Operator [].

+1

+1: Ob Sie Zugriff auf Ihre interne Darstellung (Iterator) oder nicht (Zeiger) bieten, ist der wichtigste Unterschied. –

3

IIF die interne Darstellung eine Liste von Formen sein, dann sind Zeiger und Iteratoren sicher. Sobald ein Element zugewiesen ist, wird keine Verlagerung jemals stattfinden. Ich würde keinen Index für offensichtliche Zugangsleistungsgründe empfehlen. O (n) bei Listen.

Wenn Sie einen Vektor verwenden, verwenden Sie keine Iteratoren oder Zeiger, da Elemente verschoben werden können, wenn Sie die Vektorkapazität überschreiten und Ihre Zeiger/Iteratoren ungültig werden.

Wenn Sie eine Darstellung wollen, die unabhängig von dem inneren Behälter sicher ist, erstellen Sie einen Behälter (Liste/Vektor) von Zeigern auf Ihre Formen, und geben die Form Zeiger auf Ihrem Client. Selbst wenn der Container im Speicher verschoben wird, bleiben die Shape-Objekte am selben Ort.

3

Iteratoren sind nicht sicherer als Zeiger, aber sie haben viel bessere Diagnose als rohe Zeiger, wenn Sie ein verwenden Überprüfung der STL-Implementierung!

Zum Beispiel, in einem Debug-Build, wenn Sie einen Zeiger auf ein Listenelement zurückgeben, dann löschen Sie dieses Listenelement, Sie haben einen baumelnden Zeiger. Wenn Sie darauf zugreifen, bekommen Sie einen Absturz und alles, was Sie sehen können, ist Junk-Daten. Das kann es schwierig machen herauszufinden, was falsch gelaufen ist.

Wenn Sie einen Iterator verwenden und Sie haben eine STL-Implementierung überprüft, sobald Sie den Iterator zu einem gelöschten Element zugreifen, erhalten Sie eine Nachricht so etwas wie „Iterator wurde für ungültig erklärt“. Das liegt daran, dass Sie das Element gelöscht haben, auf das es zeigt. Boom, du hast dir gerade eine Menge Debugging-Aufwand erspart.

Also nicht Indizes für O (n) Leistung. Zwischen Zeigern und Iteratoren - immer Iteratoren!

Verwandte Themen