2013-03-01 5 views
5

Ich habe eine Liste . Diese Liste ist nicht null und hat einige Werte. Mein Problem ist, wie man auf Gegenstände richtig zugreift? Ich muss nicht über die Liste iterieren. ich will nur den ersten Gegenstand.Zugriff auf das erste Element von std :: list?

std::list<T*>::iterator it = l->begin(); 

if (it != l->end()) 
{ 
    // accessing T 
    int value = (*it)->value(); // Is this safe? 
} 

oder sollte ich auch auf null überprüfen?

+0

Sie halten Zeiger, so überprüfen Sie für 'NULL'. Oder verwenden Sie eine 'std :: list '. – juanchopanza

+3

Was hat Sie dazu gebracht, 'std :: list ' anstelle von 'std :: list ' zu verwenden? – LihO

+0

Ist es wirklich notwendig, rohe Zeiger zu verwenden? ... –

Antwort

8

Wenn Sie std::list<T*> myList; zu verwenden sind gezwungen, und lassen Sie uns sagen, dass T ist wie folgt definiert:

struct T 
{ 
    T(const char* cstr) : str(cstr){ } 
    std::string str; 
}; 

dann benutzen Sie einfach std::list::front erste Element zuzugreifen:

std::string firstStr = myList.front()->str; 

Beachten Sie, dass in diesem Fall myList.front() zurückkehrt ein Verweis auf das erste Element in Ihrer Liste, in diesem Fall Verweis auf den Zeiger. Sie können es also wie einen Zeiger auf das erste Element behandeln.

Und zu Ihrer Frage über die NULL: Wenn Sie mit dem Container von Zeigern arbeiten, sollte der Zeiger aus dem Container entfernt werden, sobald das Objekt zerstört wird. Sobald Sie anfangen, Zeiger zu verwenden, bedeutet das normalerweise, dass Sie derjenige sind, der für die Speicherverwaltung verantwortlich ist, die mit Objekten verbunden ist, auf die diese Zeiger zeigen (was der Hauptgrund ist, warum Sie immer std::list<T> über std::list<T*> bevorzugen sollten).

Noch schlimmer als NULL Zeiger sind baumelnden Zeiger: Wenn Sie ein Objekt erstellen, speichern Sie die Adresse in Ihrem Container, aber Sie werden diese Adresse aus dem Behälter nicht entfernen, sobald das Objekt zerstört ist, dann ist dieser Zeiger ungültig werden und versuchen, auf den Speicher zuzugreifen, auf den dieser Zeiger zeigt, undefined Verhalten. So sollten Sie nicht nur sicherstellen, dass Ihr std::list keine NULL Zeiger enthält, Sie sollten auch sicherstellen, dass es nur Zeiger auf gültige Objekte enthält, die noch existieren.

Also von der Zeit werden Sie diese Elemente werden Aufräumen, werden Sie sich Hinweise aus der Liste zu entfernen und auf einmal Objekte zeigen sie löschen zu:

std::list<T*> myList; 

myList.push_back(new T("one")); 
myList.push_back(new T("two")); 
myList.push_back(new T("three")); 
myList.push_back(new T("four")); 

while (!myList.empty()) 
{ 
    T* pT = myList.front();      // retrieve the first element 
    myList.erase(myList.begin());    // remove it from my list 
    std::cout << pT->str.c_str() << std::endl; // print its member 
    delete pT;         // delete the object it points to 
} 

Es ist auch diese Fragen zu lesen wert:
Can you remove elements from a std::list while iterating through it?
Doesn't erasing std::list::iterator invalidates the iterator and destroys the object?

+0

isnt .front() eine gelöschte Funktion zur Zeit? Wenn ja, was stattdessen zu verwenden? – serup

0

Die Notwendigkeit einer Nullprüfung des Listenelements hängt ganz davon ab, was überhaupt in die Liste aufgenommen werden kann.

Wenn es möglich ist, dass die Liste Nullzeiger enthält, sollten Sie unbedingt nach NULL suchen, bevor Sie auf das Element zugreifen.
Wenn es nicht möglich ist, dann gibt es auch keinen Grund zu überprüfen.

+0

Ich stimme nicht zu, sollten Sie immer auf NULL überprüfen, vor allem in DEBUG/Development Builds. Wenn es nicht NULL ist, werfen Sie eine Ausnahme aus. –

+0

@AlexChamberlain: Überprüfen Sie in diesem Fall auch, ob der Zeiger sich immer noch auf ein gültiges, lebendes Objekt bezieht. –

+0

Wenn mir ein Weg einfallen würde, würde ich in einem DEBUG bauen. –

Verwandte Themen