
在 C++ 标准模板库(STL)中,std::list 是一个非常灵活且强大的双向链表容器。它提供了高效的插入和删除操作,非常适合需要频繁动态调整元素的场景。
std::list 的构造方法std::list 提供了多种构造方法,以满足不同的初始化需求:
std::list<int> myList;这会创建一个空的 std::list,不包含任何元素。
std::list<int> myList(5); // 创建一个包含 5 个默认初始化为 0 的 int 元素的 list你可以指定初始大小,并且可以为元素提供默认值:
std::list<int> myList(5, 10); // 创建一个包含 5 个值为 10 的 int 元素的 list你可以使用另一个容器的内容来初始化 std::list:
std::vector<int> vec = {1, 2, 3, 4, 5};
std::list<int> myList(vec.begin(), vec.end()); // 从 vector 的内容构造 liststd::list<int> myList = {1, 2, 3, 4, 5};这种方式简洁明了,非常适合快速初始化。
std::list 的迭代器std::list 是一个双向链表,因此它提供的是双向迭代器。这意味着你可以通过迭代器向前或向后遍历列表。
std::list<int>::iterator it = myList.begin(); // 获取指向第一个元素的迭代器
std::list<int>::iterator end = myList.end(); // 获取指向最后一个元素之后的迭代器begin() 和 end() 分别返回指向第一个元素和最后一个元素之后的迭代器。
你可以通过迭代器访问和修改元素:
for (std::list<int>::iterator it = myList.begin(); it != myList.end(); ++it) {
std::cout << *it << " "; // 访问元素
*it = *it * 2; // 修改元素
}如果你只需要读取元素,而不需要修改它们,可以使用常量迭代器:
for (std::list<int>::const_iterator cit = myList.cbegin(); cit != myList.cend(); ++cit) {
std::cout << *cit << " ";
}std::list 的容量std::list 是一个动态容器,其容量会根据元素的添加和删除自动调整。不过,它也提供了一些方法来管理容量:
if (myList.empty()) {
std::cout << "List is empty." << std::endl;
}empty() 方法返回一个布尔值,表示列表是否为空。
std::cout << "Number of elements: " << myList.size() << std::endl;size() 方法返回列表中元素的数量。
myList.clear();clear() 方法会移除列表中的所有元素,但不会释放内存。
std::list 的元素访问由于 std::list 是一个链表结构,它不支持随机访问,因此没有像数组或 std::vector 那样的下标操作符 []。不过,你可以通过迭代器来访问元素:
std::list<int>::iterator it = myList.begin();
std::cout << *it << std::endl; // 访问第一个元素如果你需要频繁访问特定位置的元素,建议使用其他容器(如 std::vector)。
std::list 的元素修改std::list 提供了多种方法来添加、删除和修改元素:
在头部添加元素
myList.push_front(10);在尾部添加元素
myList.push_back(20);在指定位置插入元素
std::list<int>::iterator it = myList.begin();
myList.insert(it, 15); // 在第一个元素之前插入 15删除头部元素
myList.pop_front();删除尾部元素
myList.pop_back();删除指定位置的元素
std::list<int>::iterator it = myList.begin();
myList.erase(it); // 删除第一个元素你可以通过迭代器直接修改元素:
std::list<int>::iterator it = myList.begin();
*it = 100; // 修改第一个元素的值std::list 的迭代器失效问题在使用 std::list 时,迭代器失效是一个需要注意的问题。迭代器失效是指迭代器不再指向有效的元素,这通常发生在对容器进行修改操作时。
插入操作:在 std::list 中插入元素不会使任何迭代器失效。这是因为 std::list 是一个双向链表,插入操作不会影响已有的元素位置。
删除操作:当你删除一个元素时,指向该元素的迭代器会失效。例如:
std::list<int>::iterator it = myList.begin();
myList.erase(it); // it 现在失效如果你需要继续使用迭代器,应该在删除操作后获取新的迭代器:
std::list<int>::iterator it = myList.begin();
it = myList.erase(it); // it 现在指向下一个有效元素erase() 方法会返回指向下一个有效元素的迭代器。remove_if() 或 remove() 方法,或者使用一个临时迭代器来管理删除操作。std::list 与 std::vector 的对比std::list:双向链表std::list 是一个双向链表结构。每个元素通过指针(或引用)与前一个元素和后一个元素相连。链表结构使得 std::list 在插入和删除操作上非常高效,但不支持随机访问。
std::vector:动态数组std::vector 是一个动态数组结构。它在内存中以连续的方式存储元素,支持快速的随机访问,但在插入和删除操作(尤其是非尾部操作)上可能效率较低。
std::liststd::list 的每个元素单独分配内存,因此内存分配较为分散。std::list 的内存开销相对较大。std::vectorstd::vector 的内存是连续分配的。它会根据需要动态调整内存大小,但每次调整可能会涉及内存复制。std::vector 的内存开销相对较小,因为它只需要存储元素本身,而不需要额外的指针。std::liststd::vectorstd::liststd::vectorstd::liststd::vector操作类型 | std::list | std::vector |
|---|---|---|
插入(任意位置) | O(1) | O(n) |
删除(任意位置) | O(1) | O(n) |
随机访问 | O(n) | O(1) |
遍历 | O(n) | O(n) |
std::list:内存使用较为分散,每个元素需要额外的指针空间。std::vector:内存使用较为紧凑,但可能需要预留额外空间以支持动态扩展。std::list 适用场景std::vector 适用场景