第六章 类、结构体、指针、引用

本文介绍了C++中的类与结构体的概念,包括成员变量的访问控制,以及如何使用它们封装数据。同时讲解了指针的基本操作,如指向内存地址和修改变量值,并探讨了引用作为变量别名的特点。此外,还通过实例展示了链表的创建、插入、删除等基本操作,并提出了链表合并的编程挑战。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 类和结构体

1.1 类的定义

在这里插入图片描述
类中的变量和函数被统一称为类的成员变量。
private后面的内容是私有成员变量,在类的外部不能访问;public后面的内容是公有成员变量,在类的外部可以访问。

1.2 类的使用

#include <iostream>

using namespace std;

const int N = 1000010;

class Person
{
    private:
        int age, height;
        double money;
        string books[100];
    
    public:
        string name;
        
        void say()
        {
            cout << "I'm " << name << endl;
        }
        
        int set_age(int a)
        {
            age = a;
        }
        
        int get_age()
        {
            return age;
        }
    
        void add_money(double x)
        {
            money += x;
        }
} person_a, person_b, persons[100];

int main()
{
    Person c;
    
    c.name = "yxc";      // 正确!访问公有变量
    c.age = 18;          // 错误!访问私有变量
    c.set_age(18);       // 正确!set_age()是共有成员变量
    c.add_money(100);
    
    c.say();
    cout << c.get_age() << endl;
    
    return 0;
}

1.3 结构体与类的联系与区别

结构体和类的作用是一样的。不同点在于类默认是private,结构体默认是public。
在这里插入图片描述

1.4 结构体的用途

结构体多用来封装一组数据

2 指针和引用

2.1 指针

指针指向存放变量的值的地址。因此我们可以通过指针来修改变量的值。
在这里插入图片描述
数组名是一种特殊的指针。指针可以做运算:

在这里插入图片描述

2.2 引用

引用和指针类似,相当于给变量起了个别名
在这里插入图片描述

3 链表(结构体、指针)

3.1 链表基本操作

在这里插入图片描述
头结点:第一个节点的地址

#include <iostream>
#include <cstdio>

using namespace std;

struct Node{
    int val;
    Node* next;
    
    Node(int n_val):val(n_val),next(NULL){}
};

int main()
{
    Node* p = new Node(1);
    Node* q = new Node(2);
    Node* o = new Node(3);
    
    Node* head = p; //头指针,第一个节点
    p->next = q;
    q->next = o;
    
    //插入节点
    Node* u = new Node(4);
    u->next = head;
    head = u;
    
    //删除1节点
    head->next = head->next->next;
    
    //链表的遍历
    for(Node* i = head; i != NULL; i = i->next){
        cout<<i->val<<endl;
    }
    
    return 0;
}

3.2 链表习题

1 合并两个排序的链表

输入两个递增排序的链表,合并这两个链表并使新链表中的结点仍然是按照递增排序的。

样例
输入:1->3->5 , 2->4->5

输出:1->2->3->4->5->5
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* merge(ListNode* l1, ListNode* l2) {
        ListNode* l3 = new ListNode(-1);//建立一个头结点
        ListNode* tail = l3; //指向链表的尾结点,尾插法插入结点
        
        while(l1 && l2)
        {
            if(l1->val <= l2->val)
            {
                //插入l1的节点
                tail->next = l1;
                l1 = l1->next;
                tail = tail->next;//指向当前链表尾结点
            }else{
                //插入l2的节点
                tail->next = l2;
                l2 = l2->next;
                tail = tail->next;
            }
        }
        
        //当某个链表移动到结尾如l1 = l1->next == NULL,接上l2剩下的全部即可,反之
        if(l1 == NULL){
            tail->next = l2;
        }else{
            tail->next = l1;
        }
        
        return l3->next;
    }
};
<think>好的,用户现在想了解C语言中结构体指针的使用方法。我之前已经回答过关于时间格式化的问题,现在需要切换到结构体指针的主题。首先,我得回忆一下结构体指针的基本概念和使用方法,确保自己理解正确。 用户提供的引用内容里有几个关键点:结构体指针的声明、初始化、成员访问以及内存管理。需要把这些内容整合成一个连贯的教程。比如引用1提到声明结构体变量和指针,并通过指针访问成员,引用2强调指针初始化的必要性,引用4涉及指针和数组的关系,引用5提到结构体指针的结合应用。 接下来,我需要考虑用户可能的背景。他们可能已经了解结构体的基本概念,但对指针的使用还不熟悉,尤其是结构体指针。需要从基础讲起,逐步深入,避免使用过于复杂的术语,同时提供代码示例帮助理解。 然后,我应该组织教程的结构。可能分为几个部分:结构体指针的定义、初始化、访问成员、动态内存分配、作为函数参数传递以及常见错误。每个部分都需要清晰的解释和示例代码。例如,在动态内存分配部分,要说明为什么需要malloc和free,以及不这样做会导致什么问题,引用2中提到的初始化问题尤其重要。 还要注意用户可能遇到的常见错误,比如未初始化指针、访问已释放的内存等,引用2和引用4中的内容可以在这里引用。同时,需要强调指针型匹配的重要性,如引用4提到的数组和指针型一致的问题,可能也需要在结构体指针中提及。 另外,用户之前的提问涉及时间格式化,可能他们对结构体的应用场景比较感兴趣,比如在时间处理中使用结构体指针。可以在应用场景部分举一些实际的例子,比如管理多个时间结构体,使用指针数组等,这样用户能更好地理解其用途。 最后,要确保回答符合之前的格式要求:使用中文,数学表达式用$...$,代码块正确,结构清晰。同时生成相关问题,帮助用户进一步学习。需要检查是否有遗漏的重要点,比如结构体指针普通指针的区别,或者结构体对齐的问题(引用3提到结构体成员排列,但用户的问题可能不直接相关,可以简要提及或忽略)。 总结一下,回答的结构可能包括定义声明、初始化、访问成员、动态内存管理、函数参数传递、应用场景和常见错误。每个部分配以代码示例和解释,确保用户能够逐步理解和应用结构体指针。</think>以下是关于C语言结构体指针使用的完整教程,结合内存管理和实际应用场景: --- ### 一、结构体指针基础 #### 1. 定义声明 ```c struct Student { // 定义结构体型 char name[20]; int age; float score; }; // 声明结构体变量和指针 struct Student stu1; // 结构体变量 struct Student *pStu; // 结构体指针 ``` #### 2. 指针初始化(关键步骤) ```c // 静态初始化:指向已有结构体变量 pStu = &stu1; // 动态初始化:申请堆内存(必须配合free()使用) pStu = (struct Student*)malloc(sizeof(struct Student)); if(pStu == NULL) { printf("内存分配失败"); exit(1); } ``` --- ### 二、结构体指针操作 #### 1. 成员访问方法 ```c // 箭头运算符访问(推荐方式) pStu->age = 18; strcpy(pStu->name, "张三"); // 等价于 (*pStu).age = 18; // 注意括号不可省略 ``` #### 2. 动态内存管理流程 ```c struct Student *createStudent() { struct Student *p = malloc(sizeof(struct Student)); p->age = 20; return p; } void destroyStudent(struct Student *p) { free(p); // 必须malloc配对使用 p = NULL; // 避免野指针 } ``` --- ### 三、高级应用场景 #### 1. 指针数组管理多个结构体 ```c struct Student *class[50]; // 存储50个学生指针 // 初始化数组 for(int i=0; i<50; i++) { class[i] = malloc(sizeof(struct Student)); class[i]->score = 0.0f; // 初始分数清零 } ``` #### 2. 作为函数参数传递 ```c void modifyScore(struct Student *s, float newScore) { if(s != NULL) { s->score = newScore; } } // 调用示例 modifyScore(pStu, 95.5f); ``` --- ### 四、内存管理注意事项 1. **必须初始化原则**: ```c struct Student *p; // 错误!未初始化 p->age = 10; // 崩溃风险(访问随机地址) ``` 2. **内存泄漏防范**: ```c pStu = malloc(...); // 第一次分配 pStu = malloc(...); // 错误!原内存块丢失 ``` 3. **结构体指针大小恒定性**: ```c printf("%zu", sizeof(pStu)); // 32位系统输出4,64位输出8 ``` --- ### 五、综合示例(学生管理系统片段) ```c #include <stdio.h> #include <stdlib.h> #include <string.h> struct Student { char id[10]; char name[20]; float scores[3]; }; void inputStudent(struct Student *s) { printf("输入学号:"); scanf("%9s", s->id); printf("输入姓名:"); scanf("%19s", s->name); } void printStudent(const struct Student *s) { printf("学号:%s\n姓名:%s\n", s->id, s->name); } int main() { struct Student *p = malloc(sizeof(struct Student)); inputStudent(p); printStudent(p); free(p); return 0; } ``` --- ### 六、常见错误排查 | 错误型 | 示例代码 | 解决方法 | |-------------------------|-------------------------------|------------------------------| | 野指针访问 | `struct Student *p; p->age=1` | 初始化指针或置为NULL | | 内存泄漏 | 连续malloc不free | 确保每个malloc都有对应的free | | 型不匹配 | `int *p = &stu.age` | 使用正确指针型 | | 访问已释放内存 | free后继续使用指针 | free后立即置NULL | ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值