• C++
  • C++ 结构体动态结构体 动态内存分配学习笔记

  • @ 2025-8-10 14:15:27

C++ 结构体动态结构体 动态内存分配学习笔记

1. 结构体基础回顾

结构体(struct)是 C++ 中一种用户自定义的数据类型,允许将不同类型的数据项组合在一起。

// 定义一个简单的结构体
struct Student {
    char name[50];  // 姓名
    int age;        // 年龄
    float score;    // 分数
};

2. 结构体的动态内存分配

动态内存分配允许程序在运行时根据需要分配和释放内存,这对于处理不确定数量的数据非常有用。

2.1 单个结构体实例的动态分配

使用 new 运算符为单个结构体实例分配内存:

#include <iostream>
#include <cstring>

struct Student {
    char name[50];
    int age;
    float score;
};

int main() {
    // 动态分配一个Student结构体
    Student* studentPtr = new Student;
    
    // 访问结构体成员(使用->运算符)
    strcpy(studentPtr->name, "张三");
    studentPtr->age = 20;
    studentPtr->score = 95.5;
    
    // 输出信息
    std::cout << "姓名: " << studentPtr->name << std::endl;
    std::cout << "年龄: " << studentPtr->age << std::endl;
    std::cout << "分数: " << studentPtr->score << std::endl;
    
    // 释放动态分配的内存
    delete studentPtr;
    studentPtr = nullptr;  // 避免悬空指针
    
    return 0;
}

2.2 结构体数组的动态分配

使用 new[] 为结构体数组分配内存:

#include <iostream>
#include <cstring>

struct Student {
    char name[50];
    int age;
    float score;
};

int main() {
    int n;
    std::cout << "请输入学生数量: ";
    std::cin >> n;
    
    // 动态分配结构体数组
    Student* students = new Student[n];
    
    // 为每个学生赋值
    for (int i = 0; i < n; i++) {
        std::cout << "请输入第" << i+1 << "个学生的信息:" << std::endl;
        std::cout << "姓名: ";
        std::cin >> students[i].name;
        std::cout << "年龄: ";
        std::cin >> students[i].age;
        std::cout << "分数: ";
        std::cin >> students[i].score;
    }
    
    // 输出所有学生信息
    std::cout << "\n所有学生信息:" << std::endl;
    for (int i = 0; i < n; i++) {
        std::cout << "学生" << i+1 << ":" << std::endl;
        std::cout << "  姓名: " << students[i].name << std::endl;
        std::cout << "  年龄: " << students[i].age << std::endl;
        std::cout << "  分数: " << students[i].score << std::endl;
    }
    
    // 释放数组内存
    delete[] students;
    students = nullptr;  // 避免悬空指针
    
    return 0;
}

3. 结构体中包含指针成员的情况

当结构体包含指针成员时,需要特别注意动态内存管理,避免内存泄漏。

4. 动态结构体的浅拷贝与深拷贝

当结构体包含指针成员时,简单的赋值操作会导致浅拷贝问题:

// 浅拷贝问题示例
Student* s1 = new Student;
s1->setName("赵六");

Student* s2 = new Student;
*s2 = *s1;  // 浅拷贝:只复制指针值,不复制指向的内容

delete s1;  // 释放s1的name内存
// 此时s2->name成为悬空指针,访问它会导致未定义行为

解决方法是实现深拷贝:

// 在Student结构体中添加深拷贝函数
void deepCopy(const Student& other) {
    setName(other.name);  // 使用已有的setName进行深拷贝
    age = other.age;
    score = other.score;
}

// 使用方式
Student* s1 = new Student;
s1->setName("赵六");

Student* s2 = new Student;
s2->deepCopy(*s1);  // 深拷贝

delete s1;  // 安全释放
// s2仍然可以正常使用

5. 常见错误与最佳实践

  1. 内存泄漏:忘记使用 deletedelete[] 释放动态分配的内存

  2. 悬空指针:使用已被释放的内存指针

  3. 重复释放:对同一块内存释放多次

  4. 最佳实践

    • 始终配对使用 newdeletenew[]delete[]
    • 释放内存后将指针设置为 nullptr
    • 结构体包含指针成员时,实现适当的拷贝和析构函数
    • 考虑使用智能指针(如 std::unique_ptrstd::shared_ptr)管理动态内存

6. 智能指针与结构体

C++11 引入的智能指针可以自动管理内存,减少内存泄漏风险:

#include <memory>  // 包含智能指针头文件

// 使用unique_ptr管理结构体
std::unique_ptr<Student> student = std::make_unique<Student>();
student->setName("孙七");

// 使用unique_ptr管理结构体数组
std::unique_ptr<Student[]> studentArray = std::make_unique<Student[]>(5);

智能指针会在超出作用域时自动释放所管理的内存,大大简化了动态内存管理。

通过以上内容,你应该已经掌握了 C++ 结构体动态内存分配的基本概念和使用方法。实践中要特别注意内存管理,避免常见的内存相关错误。

0 条评论

目前还没有评论...