源代码:
#include <iostream>
#include <list>using namespace std;int main(){list<int> numbers={10,20,30};numbers.push_front(5);numbers.push_back(40);auto it =numbers.begin();advance(it,2);numbers.insert(it,15);cout<<"该列表的数为:";for(int num:numbers){cout<<num<<"\t";}numbers.remove(15);numbers.push_front(99);numbers.sort();cout<<endl;cout<<"该列表的数为:";for(int num:numbers){cout<<num<<"\t";}
}
运行结果:
该列表的数为:5 10 15 20 30 40
该列表的数为:5 10 20 30 40 99
请按任意键继续. . .
代码详解与相关知识:
C++ std::list
代码解析及与C语言的对比
原始代码解析
#include <iostream>
#include <list>using namespace std;int main(){// 初始化一个包含3个元素的listlist<int> numbers = {10, 20, 30};// 在头部插入元素5numbers.push_front(5);// 在尾部插入元素40numbers.push_back(40);// 获取迭代器并前进2个位置auto it = numbers.begin();advance(it, 2);// 在指定位置插入15numbers.insert(it, 15);// 输出当前列表cout << "该列表的数为:";for(int num : numbers){cout << num << "\t";}// 删除所有值为15的元素numbers.remove(15);// 在头部插入99numbers.push_front(99);// 排序列表numbers.sort();// 输出最终列表cout << endl;cout << "该列表的数为:";for(int num : numbers){cout << num << "\t";}
}
代码执行流程
初始化列表:
[10, 20, 30]
头部插入5:
[5, 10, 20, 30]
尾部插入40:
[5, 10, 20, 30, 40]
在位置2插入15:
[5, 10, 15, 20, 30, 40]
删除15:
[5, 10, 20, 30, 40]
头部插入99:
[99, 5, 10, 20, 30, 40]
排序后:
[5, 10, 20, 30, 40, 99]
C语言实现对比
C语言链表实现(等效功能)
#include <stdio.h>
#include <stdlib.h>typedef struct Node {int data;struct Node* prev;struct Node* next;
} Node;Node* createNode(int value) {Node* newNode = (Node*)malloc(sizeof(Node));newNode->data = value;newNode->prev = NULL;newNode->next = NULL;return newNode;
}void insertFront(Node** head, int value) {Node* newNode = createNode(value);if (*head == NULL) {*head = newNode;return;}newNode->next = *head;(*head)->prev = newNode;*head = newNode;
}void insertBack(Node** head, int value) {Node* newNode = createNode(value);if (*head == NULL) {*head = newNode;return;}Node* temp = *head;while (temp->next != NULL) {temp = temp->next;}temp->next = newNode;newNode->prev = temp;
}void insertAt(Node** head, int position, int value) {if (position == 0) {insertFront(head, value);return;}Node* newNode = createNode(value);Node* temp = *head;for (int i = 0; temp != NULL && i < position - 1; i++) {temp = temp->next;}if (temp == NULL) {free(newNode);return;}newNode->next = temp->next;if (temp->next != NULL) {temp->next->prev = newNode;}temp->next = newNode;newNode->prev = temp;
}void deleteValue(Node** head, int value) {Node* current = *head;while (current != NULL) {if (current->data == value) {if (current->prev != NULL) {current->prev->next = current->next;} else {*head = current->next;}if (current->next != NULL) {current->next->prev = current->prev;}Node* toDelete = current;current = current->next;free(toDelete);} else {current = current->next;}}
}void printList(Node* head) {Node* temp = head;while (temp != NULL) {printf("%d\t", temp->data);temp = temp->next;}printf("\n");
}// 简化的排序实现(实际应该用更高效的排序)
void sortList(Node** head) {if (*head == NULL || (*head)->next == NULL) return;int swapped;Node* ptr1;Node* lptr = NULL;do {swapped = 0;ptr1 = *head;while (ptr1->next != lptr) {if (ptr1->data > ptr1->next->data) {int temp = ptr1->data;ptr1->data = ptr1->next->data;ptr1->next->data = temp;swapped = 1;}ptr1 = ptr1->next;}lptr = ptr1;} while (swapped);
}int main() {Node* head = NULL;// 初始化三个节点insertBack(&head, 10);insertBack(&head, 20);insertBack(&head, 30);// 头部插入5insertFront(&head, 5);// 尾部插入40insertBack(&head, 40);// 在位置2插入15insertAt(&head, 2, 15);printf("该列表的数为:");printList(head);// 删除值为15的节点deleteValue(&head, 15);// 头部插入99insertFront(&head, 99);// 排序sortList(&head);printf("该列表的数为:");printList(head);// 释放内存(实际应用中需要完整实现)return 0;
}
C++与C实现的关键区别
特性 | C++ std::list | C语言实现 |
---|---|---|
内存管理 | 自动管理(RAII) | 需手动malloc/free |
类型安全 | 模板实现,类型安全 | void*可能造成类型不安全 |
代码复杂度 | 简洁,高级抽象 | 冗长,需处理底层细节 |
功能完整性 | 提供完整成员函数(sort, merge等) | 需自行实现所有功能 |
异常安全 | 强异常安全保证 | 无异常处理机制 |
迭代器 | 提供标准迭代器 | 需手动用指针遍历 |
性能优化 | 经过高度优化 | 实现质量取决于程序员 |
可维护性 | 接口稳定,文档完善 | 维护成本高 |
线程安全 | 不同实例可并发访问 | 完全无线程安全保证 |
扩展性 | 可轻松与其他STL组件配合 | 需额外工作与其他模块集成 |
关键差异详解
1. 内存管理
C++:利用构造函数/析构函数自动管理内存
{list<int> myList; // 自动初始化// ... 使用list ... } // 自动释放所有内存
C:需手动分配和释放
Node* head = NULL; // 初始化 // ... 使用链表 ... // 必须手动释放所有节点 while (head != NULL) {Node* temp = head;head = head->next;free(temp); }
2. 迭代器 vs 指针
C++迭代器:
for (auto it = myList.begin(); it != myList.end(); ++it) {cout << *it << " "; }
C指针遍历:
Node* current = head; while (current != NULL) {printf("%d ", current->data);current = current->next; }
3. 高级操作
C++内置算法:
myList.sort(); // 内置排序 myList.unique(); // 去重 myList.merge(otherList); // 合并
C需手动实现:
sortList(&head); // 自己实现的排序 removeDuplicates(&head); // 自己实现的去重 mergeLists(&head1, &head2); // 自己实现的合并
4. 类型安全
C++模板:
list<string> stringList; // 只能存储字符串 stringList.push_back(10); // 编译错误
C无类型检查:
typedef struct Node {void* data; // 无类型安全 } Node;Node* node = (Node*)malloc(sizeof(Node)); node->data = (void*)10; // 可能造成问题
为什么选择C++ list?
开发效率:减少样板代码,专注业务逻辑
安全性:自动内存管理避免内存泄漏
可维护性:标准接口更易于理解和维护
性能:标准库实现通常经过充分优化
可扩展性:与其他STL组件无缝协作
何时需要用C实现?
嵌入式系统等受限环境(无STL支持)
需要完全控制内存布局和分配策略
与现有C代码库集成
特殊性能需求(如自定义内存池)
现代C++改进(C++11/14/17)
初始化列表:
list<int> nums = {1, 2, 3}; // C++11
自动类型推导:
auto it = nums.begin(); // 不需要写list<int>::iterator
emplace操作:
nums.emplace_back(10); // 避免临时对象构造
范围for循环:
for (int num : nums) { ... } // 简洁遍历
结构化绑定(C++17):
for (auto& [index, value] : enumerate(nums)) { ... }
理解这些差异有助于根据项目需求选择合适的实现方式。对于大多数现代C++项目,std::list
是更优的选择,而在特定场景下可能需要考虑C实现。