14

我有一个清单std::list<T *> *l;。此列表不为空并且具有一些值。我的问题是如何正确访问项目?我不需要遍历列表。我只想要第一项。

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

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

还是我也应该检查 null ?

if (it != l->end() && (*it))
{
    // accessing T
    int value = (*it)->value();
}
4

2 回答 2

16

如果您被迫使用std::list<T*> myList;,假设T定义为:

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

然后只需使用std::list::front访问第一个元素:

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

请注意,在这种情况下,myList.front()返回对列表中第一个元素的引用,在这种情况下是对指针的引用。因此,您可以将其视为指向第一个元素的指针。

关于你的问题NULL:当你使用指针容器时,一旦对象被破坏,指针应该从容器中删除。std::list<T>一旦开始使用指针,通常意味着您将负责与这些指针指向的对象相关的内存管理(这是您应该尽可能优先选择的主要原因std::list<T*>)。

NULL指针更糟糕的是悬空指针:当你创建一个对象时,将它的地址存储在你的容器中,但是一旦对象被破坏,你就不会从容器中删除这个地址,那么这个指针将变得无效并试图访问内存这个指针指向会产生未定义的行为。因此,您不仅应该确保您的std::list不包含NULL指针,还应该确保它只包含指向仍然存在的有效对象的指针。

因此,当您清理这些元素时,您会发现自己从列表中删除指针并立即删除它们指向的对象:

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
}

这些问题也值得阅读:
您可以在迭代时从 std::list 中删除元素吗?
擦除 std::list::iterator 不会使迭代器无效并破坏对象吗?

于 2013-03-01T10:59:43.473 回答
0

是否需要对列表元素进行空检查完全取决于首先可以放入列表中的内容。

如果列表可能包含空指针,那么您绝对应该在访问元素之前检查 NULL。
如果不可能,那么也没有理由去检查。

于 2013-03-01T10:23:08.030 回答