🔧 C++ 指针应用 - L26 进阶概念

掌握动态内存分配、指针数组、智能指针等高级应用

📚 动态内存管理概述

为什么需要动态内存?

在程序运行时,有时我们无法预先知道需要多少内存。动态内存分配允许我们在运行时根据需要申请和释放内存。

  • 灵活性强:根据实际需求分配内存
  • 节省空间:避免浪费不必要的内存
  • 生命周期可控:手动管理内存的创建和销毁
  • 数据结构基础:链表、树等动态结构的核心
💡 内存区域对比:
栈(Stack):自动管理,函数结束时释放
堆(Heap):手动管理,需要new/delete
• 动态内存在上分配

new和delete运算符

#include <iostream> using namespace std; int main() { // 动态分配单个变量 int* ptr = new int; // 分配一个int *ptr = 42; cout << "*ptr = " << *ptr << endl; // 42 // 动态分配并初始化 int* ptr2 = new int(100); // 分配并初始化为100 cout << "*ptr2 = " << *ptr2 << endl; // 100 // 释放内存 delete ptr; delete ptr2; // 设置为nullptr避免野指针 ptr = nullptr; ptr2 = nullptr; return 0; }

动态数组

#include <iostream> using namespace std; int main() { int size; cout << "输入数组大小:"; cin >> size; // 动态分配数组 int* arr = new int[size]; // 使用数组 for (int i = 0; i < size; i++) { arr[i] = i * 10; } // 输出数组 for (int i = 0; i < size; i++) { cout << arr[i] << " "; } cout << endl; // 释放数组内存(注意使用delete[]) delete[] arr; arr = nullptr; return 0; }
⚠️ 重要提醒:
• 单个对象用 delete
• 数组用 delete[]
• 忘记释放会导致内存泄漏
• 释放后设置为 nullptr 避免野指针

⚙️ 指针数组和数组指针

指针数组

#include <iostream> using namespace std; int main() { // 指针数组:数组的每个元素都是指针 int a = 10, b = 20, c = 30; int* ptrArray[3] = {&a, &b, &c}; // 访问指针数组 for (int i = 0; i < 3; i++) { cout << "*ptrArray[" << i << "] = " << *ptrArray[i] << endl; } // 实际应用:字符串数组 const char* fruits[] = {"Apple", "Banana", "Cherry"}; for (int i = 0; i < 3; i++) { cout << fruits[i] << endl; } return 0; }

二级指针的应用

#include <iostream> using namespace std; // 动态创建二维数组 int** createMatrix(int rows, int cols) { // 分配行指针数组 int** matrix = new int*[rows]; // 为每一行分配空间 for (int i = 0; i < rows; i++) { matrix[i] = new int[cols]; } return matrix; } // 释放二维数组 void deleteMatrix(int** matrix, int rows) { for (int i = 0; i < rows; i++) { delete[] matrix[i]; } delete[] matrix; } int main() { int rows = 3, cols = 4; // 创建3x4矩阵 int** matrix = createMatrix(rows, cols); // 填充数据 for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { matrix[i][j] = i * cols + j; } } // 打印矩阵 for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { cout << matrix[i][j] << "\t"; } cout << endl; } // 释放内存 deleteMatrix(matrix, rows); return 0; }

动态结构体

#include <iostream> #include <string> using namespace std; struct Student { string name; int age; double score; }; int main() { // 动态创建结构体 Student* stu = new Student; // 使用箭头运算符访问成员 stu->name = "张三"; stu->age = 18; stu->score = 95.5; cout << "姓名:" << stu->name << endl; cout << "年龄:" << stu->age << endl; cout << "成绩:" << stu->score << endl; // 释放内存 delete stu; stu = nullptr; return 0; }
🎮 互动实验:动态数组演示

输入数组大小,观察动态内存分配过程

输入大小后点击按钮...

🛠️ 智能指针简介

为什么需要智能指针?

手动管理内存容易出错:内存泄漏(忘记delete)、野指针(重复delete)、悬空指针(访问已释放的内存)。智能指针可以自动管理内存,避免这些问题。

💡 C++11引入的智能指针:
unique_ptr - 独占所有权
shared_ptr - 共享所有权(引用计数)
weak_ptr - 弱引用(配合shared_ptr使用)

unique_ptr(独占指针)

#include <iostream> #include <memory> using namespace std; int main() { // 创建unique_ptr(自动管理内存) unique_ptr<int> ptr1(new int(42)); cout << "*ptr1 = " << *ptr1 << endl; // 42 // unique_ptr不能拷贝,只能移动 // unique_ptr<int> ptr2 = ptr1; // 错误! unique_ptr<int> ptr2 = move(ptr1); // 转移所有权 if (ptr1 == nullptr) { cout << "ptr1已为空" << endl; } cout << "*ptr2 = " << *ptr2 << endl; // 42 // 不需要手动delete,离开作用域自动释放 return 0; }

shared_ptr(共享指针)

#include <iostream> #include <memory> using namespace std; int main() { // 创建shared_ptr shared_ptr<int> ptr1 = make_shared<int>(42); cout << "*ptr1 = " << *ptr1 << endl; // 42 cout << "引用计数:" << ptr1.use_count() << endl; // 1 // 可以拷贝,共享所有权 shared_ptr<int> ptr2 = ptr1; cout << "引用计数:" << ptr1.use_count() << endl; // 2 cout << "引用计数:" << ptr2.use_count() << endl; // 2 // 当最后一个shared_ptr销毁时,内存自动释放 return 0; }

智能指针的实际应用

#include <iostream> #include <memory> #include <vector> using namespace std; struct Student { string name; int age; Student(const string& n, int a) : name(n), age(a) { cout << "创建学生:" << name << endl; } ~Student() { cout << "销毁学生:" << name << endl; } }; int main() { // 使用智能指针管理对象 vector<shared_ptr<Student>> students; students.push_back(make_shared<Student>("张三", 18)); students.push_back(make_shared<Student>("李四", 19)); students.push_back(make_shared<Student>("王五", 20)); // 访问学生信息 for (const auto& stu : students) { cout << stu->name << ", " << stu->age << "岁" << endl; } // 离开作用域时,所有学生对象自动销毁 return 0; }

🚀 高级指针技术

内存泄漏检测

#include <iostream> using namespace std; // 常见的内存泄漏示例 void memoryLeakExample() { int* ptr = new int(42); // 忘记delete,导致内存泄漏! } // 正确的做法 void correctExample() { int* ptr = new int(42); cout << "*ptr = " << *ptr << endl; delete ptr; // 记得释放 ptr = nullptr; } // 使用智能指针避免泄漏 void smartPointerExample() { unique_ptr<int> ptr(new int(42)); // 自动释放,无需担心泄漏 } int main() { correctExample(); smartPointerExample(); cout << "没有内存泄漏!" << endl; return 0; }

实际应用:动态链表

#include <iostream> #include <memory> using namespace std; struct Node { int data; shared_ptr<Node> next; Node(int val) : data(val), next(nullptr) {} }; class LinkedList { private: shared_ptr<Node> head; public: LinkedList() : head(nullptr) {} // 在头部插入节点 void insertFront(int value) { auto newNode = make_shared<Node>(value); newNode->next = head; head = newNode; } // 打印链表 void printList() { auto current = head; while (current != nullptr) { cout << current->data << " -> "; current = current->next; } cout << "NULL" << endl; } }; int main() { LinkedList list; list.insertFront(3); list.insertFront(2); list.insertFront(1); cout << "链表:"; list.printList(); // 离开作用域时,所有节点自动释放 return 0; }

📝 实战练习

📝 理解测试

以下代码有什么问题?

#include <iostream> using namespace std; int main() { int* arr = new int[10]; // 使用数组... delete arr; // 这里有问题吗? return 0; }
选择答案查看解析...
💻 综合挑战

题目:编写一个程序,实现动态数组类:
1. 可以动态调整数组大小
2. 支持添加、删除元素
3. 自动管理内存(或使用智能指针)
4. 提供打印数组的功能

点击"生成代码框架"查看提示...