我有一个列表std::list<T *> *l;
。此列表不为null并且具有一些值。我的问题是如何正确访问项目?我不需要遍历列表。我只想要第一个项目。
std::list<T*>::iterator it = l->begin();
if (it != l->end())
{
// accessing T
int value = (*it)->value(); // Is this safe?
}
或者我也应该检查是否为空?
if (it != l->end() && (*it))
{
// accessing T
int value = (*it)->value();
}
答案 0 :(得分:11)
如果您被迫使用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
}
阅读这些问题也是值得的:
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?
答案 1 :(得分:0)
需要对列表元素进行空值检查完全取决于首先可以放入列表的内容。
如果列表可能包含空指针,那么在访问元素之前,你绝对应该检查NULL。
如果不可能,那么也没有理由检查。