C++ 中的 std::list(附示例)

什么是 std::list?

在 C++ 中,std::list 指的是一种存储容器。std::list 允许您在任何位置插入和删除项目。std::list 是作为双向链表实现的。这意味着列表数据可以双向和顺序访问。

标准模板库的 list 不支持快速随机访问,但支持从所有方向的顺序访问。

您可以将列表元素分散在不同的内存块中。顺序访问数据所需的信息存储在容器中。std::list 可以在运行时根据需要从两端进行扩展和收缩。内部分配器会自动满足存储要求。

为什么使用 std::list?

使用 std::List 的原因如下:

  • 与数组和 vector 等其他序列容器相比,std::list 的性能更好。
  • 它们在从任何位置插入、移动和提取元素方面具有更好的性能。
  • std::list 在执行此类操作密集型算法时表现也更好。

列表语法

要定义 std::list,我们必须导入 <list> 头文件。这是 std::list 的定义语法。

template < class Type, class Alloc =allocator<T> > class list;

以下是对上述参数的描述:

  • T – 定义包含的元素类型。您可以将 T 替换为任何数据类型,甚至是用户定义的类型。
  • Alloc – 定义分配器对象的类型。它默认使用 allocator 类模板。它是值相关的,并使用简单的内存分配模型。

示例 1

#include <algorithm>
#include <iostream>
#include <list>
int main() {
	std::list<int> my_list = { 12, 5, 10, 9 };

	for (int x : my_list) {
		std::cout << x << '\n';
	}
}

输出

std::list

这是代码的屏幕截图:

std::list

代码解释

  1. 包含算法头文件以使用其函数。
  2. 包含 iostream 头文件以使用其函数。
  3. 包含 list 头文件以使用其函数。
  4. 调用 main() 函数。程序逻辑应添加到此函数的主体中。
  5. 创建一个名为 my_list 的列表,其中包含 4 个整数。
  6. 使用 for 循环创建一个循环变量 x。此变量将用于迭代列表元素。
  7. 将列表的值打印到控制台。
  8. for 循环 主体结束。
  9. main() 函数体结束。

C++ 列表函数

以下是常见的 std::list 函数:

函数 描述
insert() 此函数在迭代器指向的位置之前插入一个新项。
push_back() 此函数在列表末尾添加一个新项。
push_front() 它在列表的开头添加一个新项。
pop_front() 它删除列表的第一个项。
size() 此函数确定列表元素的数量。
front() 确定列表的第一个项。
back() 确定列表的最后一个项。
reverse() 它反转列表项。
merge() 它合并两个已排序的列表。

<list> 构造函数

以下是 <list> 头文件提供的 函数列表:

  • 默认构造函数 std::list::list() - 它创建一个空列表,其中包含零个元素。
  • 填充构造函数 std::list::list() - 它创建一个包含 n 个元素的列表,并将每个元素的值设置为零 (0)。
  • 范围构造函数 std::list::list() - 创建一个包含从 first 到 last 范围内的多个元素的列表。
  • 复制构造函数 std::list::list() - 它创建一个列表,其中包含现有列表中每个元素的副本。
  • 移动构造函数 std::list::list() - 使用移动语义创建另一个列表元素的列表。
  • 初始化列表构造函数 std::list::list() - 使用移动语义创建另一个列表元素的列表。

示例 2

#include <iostream>
#include <list>
using namespace std;
int main(void) {
	list<int> l;
	list<int> l1 = { 10, 20, 30 };
	list<int> l2(l1.begin(), l1.end());
	list<int> l3(move(l1));  
	cout << "Size of list l: " << l.size() << endl;
	cout << "List l2 contents: " << endl;
	for (auto it = l2.begin(); it != l2.end(); ++it)
	      cout << *it << endl;
	cout << "List l3 contents: " << endl;
	for (auto it = l3.begin(); it != l3.end(); ++it)
		cout << *it << endl;
	return 0;
}

输出

list Constructors

这是代码的屏幕截图:

list Constructors

代码解释

  1. 包含 iostream 头文件以使用其函数。
  2. 包含 list 头文件以使用其函数。
  3. 包含 std 命名空间以在代码中使用其类,而无需调用它。
  4. 调用 main() 函数。程序逻辑应添加到此函数的主体中。
  5. 创建一个名为 l 的空列表。
  6. 创建一个名为 l1 的列表,其中包含 3 个整数。
  7. 创建一个名为 l2 的列表,其中包含列表 l1 中的所有元素,从开头到结尾。
  8. 使用移动语义创建一个名为 l3 的列表。列表 l3 将与列表 l2 具有相同的内容。
  9. 在控制台打印列表 l 的大小以及其他文本。
  10. 在控制台打印一些文本。
  11. 创建一个名为 it 的迭代器,并使用它来迭代列表 l2 的元素。
  12. 将列表 l2 的元素打印到控制台。
  13. 在控制台打印一些文本。
  14. 创建一个名为 it 的迭代器,并使用它来迭代列表 l3 的元素。
  15. 将列表 l3 的元素打印到控制台。
  16. 程序在成功完成后应返回值。
  17. main() 函数体结束。

容器属性

这是容器属性列表:

属性 描述
序列 序列容器按严格的线性顺序排列其元素。通过元素在序列中的位置来访问元素。
双向链表 每个元素都包含有关如何定位前一个和下一个元素的信息。这使得插入和删除操作具有恒定的时间。
分配器感知 使用分配器对象动态修改存储大小。

插入到列表中

我们可以使用不同的函数将值插入到列表中。让我们演示一下:

示例 3

#include <algorithm>
#include <iostream>
#include <list>
int main() {
	std::list<int> my_list = { 12, 5, 10, 9 };
	my_list.push_front(11);
	my_list.push_back(18);
	auto it = std::find(my_list.begin(), my_list.end(), 10);
	if (it != my_list.end()) {
		my_list.insert(it, 21);
	}
	for (int x : my_list) {
		std::cout << x << '\n';
	}
}

输出

Inserting into a List

这是代码的屏幕截图:

Inserting into a List

代码解释

  1. 包含算法头文件以使用其函数。
  2. 包含 iostream 头文件以使用其函数。
  3. 包含 list 头文件以使用其函数。
  4. 调用 main() 函数。程序逻辑应添加到此函数的主体中。
  5. 创建一个名为 my_list 的列表,其中包含 4 个整数。
  6. 将元素 11 插入到名为 my_list 的列表的开头。
  7. 将元素 18 插入到名为 my_list 的列表的末尾。
  8. 创建一个迭代器 it,并使用它从列表 my_list 中查找元素 10。
  9. 使用 if 语句确定是否找到了上述元素。
  10. 如果找到了上述元素,则在它之前插入元素 21。
  11. if 语句主体的结束。
  12. 使用 for 循环创建一个循环变量 x。此变量将用于迭代列表元素。
  13. 将列表的值打印到控制台。
  14. for 循环体的结束。
  15. main() 函数体结束。

从列表中删除

可以从列表中删除项目。erase() 函数允许您从列表中删除一个项目或一系列项目。

  • 要删除单个项目,只需传递一个整数位置。该项目将被删除。
  • 要删除一个范围,需要传递起始和结束迭代器。让我们演示一下。

示例4

#include <algorithm>
#include <iostream>
#include <list>
using namespace std;
int main() {
	std::list<int> my_list = { 12, 5, 10, 9 };
	cout << "List elements before deletion: ";
	for (int x : my_list) {
		std::cout << x << '\n';
	}
	list<int>::iterator i = my_list.begin();
	my_list.erase(i);
	cout << "\nList elements after deletion: ";
	for (int x : my_list) {
		std::cout << x << '\n';
	}
	return 0;
}

输出

Deleting from a List

这是代码的截图:

Deleting from a List

代码解释

  1. 包含算法头文件以使用其函数。
  2. 包含 iostream 头文件以使用其函数。
  3. 包含 list 头文件以使用其函数。
  4. 在程序中包含 std 命名空间,以便在使用其类时无需调用它。
  5. 调用 main() 函数。程序逻辑应添加到此函数的主体中。
  6. 创建一个名为 my_list 的列表,其中包含 4 个整数。
  7. 在控制台打印一些文本。
  8. 使用 for 循环创建一个循环变量 x。此变量将用于迭代列表元素。
  9. 将列表的值打印到控制台。
  10. for 循环体结束。
  11. 创建一个指向列表第一个元素的迭代器 i。
  12. 使用迭代器 i 指向的 erase() 函数。
  13. 在控制台打印一些文本。
  14. 使用 for 循环创建一个循环变量 x。此变量将用于迭代列表元素。
  15. 将列表的值打印到控制台。这发生在删除之后。
  16. for 循环体结束。
  17. 程序在成功完成后必须返回值。
  18. main() 函数体结束。

摘要

  • std::list 是一种存储容器。
  • 它允许在恒定时间内从任何位置插入和删除项目。
  • 它被实现为双向链接
  • std::list 数据可以双向和顺序访问。
  • std::list 不支持快速随机访问。但是,它支持从所有方向的顺序访问。
  • 您可以将 std::list 的列表元素分散在不同的内存块中。
  • 您可以根据需要在运行时从两端收缩或扩展 std::list。
  • 要将项目插入 std::list,我们使用 insert() 函数。
  • 要从 std::list 中删除项目,我们使用 erase() 函数。