笔记C++语言,太焦虑了

调查研究

Javascript

基础知识

介绍

**javascript是一种运行在客户端(浏览器)的编程语言 ,实现人机交互效果 **

  1. 作用:网页特效、表单验证、数据交互、服务器编程(node.js)

组成:

  • ECMAScripts ---> 规定js的基础语法核心知识
  • Web APIs --->
    • DOM 操作文档,比如对页面元素进行移动、大小、添加删除操作
    • BOM 操作浏览器,比如页面弹窗,检测窗口宽度、存储数据到浏览器
  1. 书写位置
  • 内部js --->写在html里面,用script标签,写在上面

  • 外部js --->代码写在js文件,引入html页面

  • 内联js --->代码写在标签内部

    js 复制代码
    <script> 
        prompt("hello,world")
    	document.write('你好,js')
    </script>
  • 注释

    单行注释 // 快捷键 Ctrl + /

​ 块注释 /* */ 快捷键 shift + alt + a

​ 结束符 --->英文分号代表语句结束 ;

  1. 输入输出语法

输出语法:向body输出内容 document.write('你好,js')

​ 页面警示框 alert('你好,js')

​ 控制台输出语法 console.log('你好,js')

输入语法: 提示输入prompt('请输入hello,world')

  1. 代码执行顺序

alert()和prompt()会跳过页面渲染先被执行

变量

  1. 变量的定义

变量是计算机存储数据的容器

  1. 变量的声明

创建变量:声明关键字、变量名

js 复制代码
let 变量名

赋值:对变量进行初始化

js 复制代码
let age = 18
//let不允许多次声明一个变量

交换两个变量的值,引入第三个变量temp

  1. 变量的本质

内存-->计算机存储数据的地方,程序在内存中申请一小块用来存放数据的小空间

  1. 变量的命名规范

由数字、字母、下划线、$符号组成,不能使用关键字,不能以数字开头;严格区分大小写

  • let和var的区别

var可以先使用在声明、声明过的变量可以重复声明;变量提升、全局变量、没有块级作用域

声明变量统一用let


  1. 常量

概念:是一个不能被修改的值,通常用于表示固定、不变的量,使用const变量

使用:const PI = 3.1415926

常量不允许重新赋值,声明的时候必须复制(初始化)

  1. 数据类型(弱数据类型语言)

①基本数据类型

number、string、boolean、undefined、null、

②引用数据类型

object、function、array

数字--number

  1. 定义:number 类型用于表示整数和浮点数,包括正数、负数和零

  2. 算术运算符 ( + - * / % >> 取余)

  3. 特别地:NaN是一个特殊的数值状态,它不等于任何值,包括自己,因此NaN != NaN

任何对NaN的操作都是返回NaN

字符串--string

  1. 用于存储文本数据的变量类型。字符串由字符组成,可以包含字母、数字、标点符号等;单引号、双引号、反引号包裹的数据
  2. 字符串拼接 '+';
  3. 模版字符串

语法:``反引号

内容拼接变量时,用${ }包裹变量

${变量名}

其他类型

  • 布尔类型---boolean

是一种数据类型,用于表示逻辑值,只有两种可能的值:true 和 false

  • 未定义类型---undefined

未定义类型"通常指的是在程序运行时,遇到的与变量类型相关的错误;声明变量未赋值

  • 空类型---null

表示一个变量被赋值为 null,将来存放对象

类型转换

typeoftypeof ()--->用于获取变量的类型

js 复制代码
let num = 10
typeof num 

隐式转换:+ 两边只要有字符串,默认为字符串计算,其他算术运算符为数字类型

+'123'可转为数字类型

Number( ) 函数可以将字符串转换为数字

parseInt( ) 函数用于将字符串转换为整数

parsefloat( ) 函数将字符串转换为浮点数

运算符

赋值运算符(=、+=)

对变量进行赋值的运算符

js 复制代码
let b = 5;
b += 3; // b现在等于8,等同于b = b + 3
一元运算符(+)

只需要一个表达式就可运算,自增++和 自减--

自增运算符

  • 前缀形式(++a):先增加值,再使用该值。
  • 后缀形式(a++):先使用原值,再增加值。

自减运算符

  • 前缀形式(--a):先减少值,再使用该值。
  • 后缀形式(a--):先使用原值,再减少值。
比较运算符(> <)

比较运算符有隐式转换

  1. <=:小于等于
  2. ==:等于
  3. !=:不等于
  4. ===:严格等于
  5. !==:严格不等于
  • 字符串比较

字符串比较转换为对应的ASCII码比较

逻辑运算符&&

逻辑与(全真为真)---&&

逻辑或(一真则真)---||

逻辑非 (非真即假)---!

流程控制语句

  • 顺序结构>>从上到下、依次执行

  • 分支结构

    1. if条件为真就执行
    2. else否则执行这里
    3. switch匹配哪个 case 就执行哪个
  • 循环结构

    1. for计数循环,条件成立就继续
    2. while先判后做,成立才循环
    3. do...while先做后判,至少执行一次
    4. for用于遍历数据结构
    • for...of:获取元素值(如数组元素、字符串字符)
    • for...in:获取键名(如对象键、数组索引字符串)
  • break和continue

break:彻底结束循环,立即跳出。

continue:跳过当前迭代,继续下一轮循环

数组array

  1. 定义

​ 数组是一个有序的存储容器,用于存储多个值。这些值可以是 primitives(如字符串、数字、 boolean、 null、 undefined)或 objects(对象)、 arrays(数组)等复杂的值。

  1. 声明语法

let 数组名 = [数据]

  1. 访问

数组名[索引号]

长度-->数组的length获得:数组名.length

  1. 遍历

i <= array.length-1,确保索引不超过数组的最后一个元素(索引为 length-1)

进阶知识

HTML

基础知识

CSS

基础知识

Linux

基础知识

前景提要

  • 计算机的主要组成部分:硬件系统和软件系统

操作系统(Operating System, OS)是计算机系统中负责管理和控制计算机及其资源的核心软件;

移动操作系统

  1. 安卓(Android)
  2. iOS
  3. 鸿蒙(HarmonyOS)

PC操作系统

  1. Windows
  2. macOS
  3. Linux

Linux的主要发行版:Ubuntu/RedHat/Centos

Windows操作系统

WSL(Windows Subsystem for Linux

  • WSL2:基于轻量级虚拟机(Hyper-V),提供完整的Linux内核,文件系统性能大幅提升,推荐使用。

Linux知识

Linux系统的组成:linux系统内核、系统级应用程序

Linux目录结构
  1. 根目录 (/):
    • Linux系统的根目录是所有其他目录的起点,通常包含操作系统和系统配置文件。
  2. 常用目录层次结构:
    • /boot:包含操作系统启动所需的文件和分区。
    • /home:用户日志、配置文件等。
    • /root:根用户的目录,通常是系统管理员的主目录。
    • /etc:环境变量、系统配置文件。
    • /user:用户目录,存储用户程序和数据。
    • /mnt:挂载点,用于连接外置文件系统。
  3. 用户目录 (/user):
    • 用户目录下通常包含用户的配置文件、应用程序的安装目录、以及用户生成的文件等。
  4. 本地目录 (/user/local):
    • 用于存储用户的本地配置文件,如密码、登录信息等,通常隐藏在用户目录下。
  5. 设备驱动层:
    • /dev:包含设备驱动和虚拟设备,如swap分区、设备映射等。

Shell编程

C++程序设计语言

基础知识

变量

命名规则:C++标识符由字母、数字和下划线组成,必须以字母或下划线开头,不能是关键字,并且区分大小写

数据的输入与输出

cout是标准输出流对象,通过<<运算符向控制台输出数据(如cout << "Hello" << endl;),endl换行;

cin是标准输入流对象,通过>>从控制台读取输入到变量(如cin >> name;)。

两者需包含头文件<iostream>,属std命名空间。

<<称插入运算符,>>为提取运算符,注意输入类型需匹配变量,字符串输入用getline()更安全。

数据类型

C++数据类型包括基本类型:整型( int、long long int)、浮点型(如 float、double)、布尔型(如 true、false)、字符型(char)和字符串型(string)、复合类型(数组array、结构体、类、联合体)、空类型(void)及引用类型

sizeof 是 C++ 中的一个一元运算符 ,用于计算数据类型或变量在内存中所占的字节数,返回值为 size_t 类型

size_t---无符号整数类型,专门用来表示 "对象大小""数组索引" 这类 非负整数值

  • sizeof(类型名)(如 sizeof(int)
  • sizeof 变量/表达式(如 sizeof(a)

科学计数法:

科学计数法的幂次是 10 的幂,float 精度约 7 位十进制,double 精度约 15 位

未指定后缀的科学计数法默认是 double 类型

例如:3e-2double,若赋值给 float 变量,添加后缀 fF

flaot f3 = 3e-2f =3*10^-2

double f3 = 3e+2 = 3*10^2

运算符

算术运算符
  • / :除法(整数除法会截断小数部分)整数相除结果依然是整数
  • %:取模(求余数,仅用于整数类型)
  • ++:自增
  • --:自减

前置运算符 --- 变量先加减,再进行表达式运算;

后置运算符 --- 先执行表达式运算,再进行变量加减

赋值运算符

=用于赋值,复合形式如+=*=可简化操作

比较运算符

用于判断两值关系,返回布尔值:

==相等、!=不等、>大于、<小于、>=大于等于、<=小于等于

逻辑运算符

&&:全真为真;||:一真即真;!:非真即假

条件运算符

语法格式为:
condition ? expression1 : expression2

c++ 复制代码
#include <iostream>
using namespace std;

int main() {
    int score = 85;
    
    // 条件运算符:condition ? expr1 : expr2
    // 如果条件为真,返回expr1;否则返回expr2
    string result = (score >= 60) ? "及格" : "不及格";
    
    cout << "分数 " << score << " 的结果是:" << result << endl;
    // 输出:分数 85 的结果是:及格
    
    return 0;
}

三目运算符返回的是变量,可以继续赋值

c++ 复制代码
#include <iostream>
using namespace std;

int main() {
    int a = 10;
    int b = 20;
    
    // 三目运算符返回的是变量本身(左值),所以可以继续赋值
    // 因为 a < b,所以 (a > b ? a : b) 返回的是 b 这个变量
    // 相当于执行了 b = 100
    (a > b ? a : b) = 100;
    
    cout << "a = " << a << ", b = " << b << endl; // 输出: a = 10, b = 100
    
    return 0;
}

流程结构

顺序结构

依次执行

  1. 程序从 main() 函数开始

  2. 逐行执行每条语句

  3. 每条语句执行完成后自动进入下一条

  4. 直到遇到 return 0; 程序结束

选择结构

if语句

简单if语句:if (条件) 语句;

  • 如果条件为真,执行语句;否则跳过

if-else语句:if (条件) 语句1; else 语句2;

  • 如果条件为真,执行语句1;否则执行语句2

if-else else-if语句:用于多条件判断

  • 依次检查每个条件,执行第一个为真的条件对应的语句

重要规则:

  • 条件表达式需要用圆括号 () 括起来
  • 如果if或else后面有多条语句,必须用花括号 {} 括起来形成代码块
  • C++中,非零值被视为真,零值被视为假

Switch语句

重要规则:

  • 类型限制:switch的判断表达式只能是整型(int, short, long等)或字符型(char),不能是浮点型、字符串或布尔型
  • 值匹配:只能匹配具体的值,不能判断区间(如case 60-70: 是错误的)
  • break的重要性:每个case后通常需要break语句,否则会"穿透"执行下一个case的代码
  • default可选:可以包含default分支处理未匹配的情况
c++ 复制代码
#include <iostream>
using namespace std;

int main() {
    char grade = 'B';
    
    cout << "成绩等级对应评语:" << endl;
    
    switch (grade) {
        case 'A':
            cout << "优秀!继续保持!" << endl;
            break;  // 必须有break,否则会继续执行下一个case
        case 'B':
            cout << "良好!很有潜力!" << endl;
            break;
        case 'C':
            cout << "及格!需要更加努力!" << endl;
            break;
        case 'D':
            cout << "不及格!要加油了!" << endl;
            break;
        case 'F':
            cout << "很差!需要重新学习!" << endl;
            break;
        default:  // 处理未匹配的情况
            cout << "无效的成绩等级!" << endl;
            break;
    }
    
    // 错误示例:尝试使用区间(这是不允许的)
    /*
    int score = 85;
    switch (score) {
        case 90-100:  // 错误!不能使用区间
            cout << "A" << endl;
            break;
        case 80-89:   // 错误!
            cout << "B" << endl;
            break;
    }
    */
    
    // 正确处理数值范围的方式应该用if-else
    int score = 85;
    cout << "\n用if-else处理分数区间:" << endl;
    if (score >= 90) {
        cout << "等级:A" << endl;
    } else if (score >= 80) {
        cout << "等级:B" << endl;
    } else if (score >= 70) {
        cout << "等级:C" << endl;
    } else if (score >= 60) {
        cout << "等级:D" << endl;
    } else {
        cout << "等级:F" << endl;
    }
    
    return 0;
}
循环结构

1. while循环

  • 语法:while (条件) { 循环体 }

  • 执行流程:

    1. 判断条件表达式是否为真
    2. 如果为真,执行循环体,然后回到判断
    3. 如果为假,跳出循环,执行循环后的代码
    c++ 复制代码
    #include <iostream>
    using namespace std;
    
    int main() {
        int i = 1;
        
        // 当i <= 5时,重复执行循环体
        while (i <= 5) {
            cout << i << " ";
            i++;  // 更新循环变量
        }
        // 输出:1 2 3 4 5
        
        return 0;
    }

2. do while循环

  • 语法
c++ 复制代码
do {
    // 循环体
} while (条件);
  • 重要规则:
    1. 至少执行一次:无论条件是否为真,循环体都会先执行一次
    2. 后判断:在每次循环体执行完毕后才检查条件
    3. 分号:while后的条件判断必须以分号结束
c++ 复制代码
#include <iostream>
using namespace std;

int main() {
    int i = 1;
    
    // 先执行循环体,再判断条件
    do {
        cout << i << " ";
        i++;
    } while (i <= 5);
    // 输出:1 2 3 4 5
    
    return 0;
}

3. for循环

  • 语法:
c++ 复制代码
for (初始化; 条件; 更新) {
    // 循环体
}
  • 重要规则:
    1. 三要素集中:初始化、条件判断、更新操作都在括号内清晰定义
    2. 预测试:先判断条件,为真时才执行循环体
    3. 适用场景:适合循环次数已知的情况

数组是用于存储相同类型多个元素的连续内存空间

利用for循环遍历数组

c++ 复制代码
#include <iostream>
using namespace std;

int main() {
    int arr[5] = {10, 20, 30, 40, 50};
    
    // 使用for循环遍历数组
    for (int i = 0; i < 5; i++) {
        cout << "arr[" << i << "] = " << arr[i] << endl;
    }
    
    return 0;
}

猜数字案例

c++ 复制代码
#include <iostream>      // 输入输出流
#include <ctime>         // time()函数获取时间
using namespace std;

int main()
{
    cout << "猜数字游戏开始!" << endl;
    
    // 1. srand() + time(NULL):设置随机数种子
    // time(NULL)返回当前时间(秒数),确保每次运行程序产生不同的随机序列
    srand(time(NULL));
    
    // 2. rand() % 100 + 1:生成1-100的随机数
    // rand()产生0-RAND_MAX的随机数
    // % 100 得到0-99,+1 变成1-100
    int a = rand() % 100 + 1;
    
    int guess = 0;
    cout << "请输入你猜的数字(1-100):" << endl;
    
    // 3. while(true)无限循环 + break:实现持续猜测直到正确
    while (true) {
        cin >> guess;  // 输入
        
        // 4. if-else if-else:多分支判断
        if (guess > a) {
            cout << "猜大了" << endl;
        }
        else if (guess < a) {
            cout << "猜小了" << endl;
        }
        else {
            cout << "恭喜你猜对了" << endl;
            break;  // 5. break:跳出循环
        }
    }

    cout << "游戏结束" << endl;
    return 0;
}

4. 跳转语句

  • break

    1. 跳出循环**:在 forwhiledo-while 循环中,立即终止整个循环**
    2. 跳出switch :在 switch 语句中,跳出当前 switch 结构,防止"穿透"到下一个case

    break 只能跳出最内层 的循环或 switch 语句

c++ 复制代码
#include <iostream>
using namespace std;

int main() {
    // break在循环中的使用
    for (int i = 1; i <= 10; i++) {
        if (i == 5) {
            break;  // 当i等于5时,立即跳出循环
        }
        cout << i << " ";  // 输出:1 2 3 4
    }
    
    return 0;
}
  • continue

    1. 跳过当前循环体中剩余的代码
    2. 直接进入下一次循环的迭代
    3. 对于 for 循环,会先执行更新表达式,再判断条件

    continue 只能在循环结构(forwhiledo-while)中使用。

c++ 复制代码
#include <iostream>
using namespace std;

int main() {
    // continue跳过偶数,只输出奇数
    for (int i = 1; i <= 10; i++) {
        if (i % 2 == 0) {
            continue;  // 如果是偶数,跳过本次循环剩余代码
        }
        cout << i << " ";  // 只有奇数能执行到这里
    }
    // 输出:1 3 5 7 9
    
    return 0;
}
  • **go to **
c++ 复制代码
goto 标签名;
...
标签名: // 标签后跟冒号

​ 1. 无条件跳转:立即跳转到标签所在位置

​ 2. 标签命名:遵循变量命名规则,后跟冒号

​ 3. 作用范围:只能在同一函数内跳转

​ 4. 限制:不能跳过变量的初始化(如跳过带初始化的定义)

c++ 复制代码
#include <iostream>
using namespace std;

int main() {
    int i = 1;
    
    loop_start:  // 定义标签
    if (i > 5) {
        goto loop_end;  // 条件满足时跳转到loop_end
    }
    cout << i << " ";
    i++;
    goto loop_start;  // 跳转回loop_start
    
    loop_end:  // 标签位置
    cout << "\n循环结束" << endl;
    
    return 0;
}
// 输出:1 2 3 4 5
//       循环结束

数组

一维数组
  1. 声明语法类型 数组名[大小];
    • 类型:数组中所有元素的数据类型(如int、double、char等)
    • 大小:数组元素的个数,必须是编译时常量(正整数)
  2. 内存布局
    • 数组元素在内存中连续存储
    • 第一个元素的索引是0,最后一个元素的索引是大小-1
    • 可以通过&数组名[索引]获取元素的内存地址
  3. 初始化方式
    • 完全初始化:int arr[3] = {1, 2, 3};
    • 部分初始化:int arr[5] = {1, 2}; (剩余元素自动初始化为0)
    • 自动大小:int arr[] = {1, 2, 3}; (编译器根据初始化值确定大小)
  4. 访问元素
    • 使用下标运算符 [],如 arr[0]
    • 不检查边界:访问超出范围的索引会导致未定义行为(如内存越界)
  5. 数组名的含义
    • 数组名代表数组首元素的地址
    • sizeof(数组名) 返回整个数组的字节数
    • 作为函数参数传递时,会退化为指针
c++ 复制代码
#include <iostream>
using namespace std;

int main() {
    // 1. 声明并初始化一维数组
    int scores[5] = {85, 92, 78, 96, 88};  // 完全初始化
    
    // 2. 访问数组元素(使用for循环)
    cout << "=== 数组元素遍历 ===" << endl;
    for (int i = 0; i < 5; i++) {
        cout << "第" << (i+1) << "个成绩: " << scores[i] << endl;
    }
    
    // 3. 修改数组元素
    scores[2] = 85;  // 将第三个元素修改为85
    cout << "\n修改后第三位成绩: " << scores[2] << endl;
    
    // 4. 数组大小计算
    cout << "数组总大小: " << sizeof(scores) << " 字节" << endl;
    cout << "单个元素大小: " << sizeof(scores[0]) << " 字节" << endl;
    cout << "元素个数: " << sizeof(scores) / sizeof(scores[0]) << endl;
    
    // 5. 内存地址演示
    cout << "\n=== 内存地址 ===" << endl;
    for (int i = 0; i < 5; i++) {
        cout << "scores[" << i << "] 地址: " << &scores[i] << endl;
    }
    cout << "数组名地址: " << scores << endl;  // 数组名即首元素地址
    
    return 0;
}
二维数组
  1. 声明语法类型 数组名[行数][列数];

    • 例如:int matrix[3][4]; 声明一个3行4列的整型数组
  2. 内存布局

    • 元素在内存中连续存储
    • 按行优先顺序:第一行所有元素 → 第二行所有元素 → ...
    • 总元素个数 = 行数 × 列数
    • 总字节数 = 行数 × 列数 × sizeof(元素类型)
  3. 初始化方式

    • 按行初始化:int arr[2][3] = {``{1,2,3}, {4,5,6}};
    • 连续初始化:int arr[2][3] = {1,2,3,4,5,6};
    • 部分初始化:未指定的元素自动初始化为0
    c++ 复制代码
    #include <iostream>
    using namespace std;
    
    int main() {
        // 1. 完整按行初始化(推荐,清晰易读)
        int arr1[2][3] = {
            {1, 2, 3},
            {4, 5, 6}
        };
        
        // 2. 连续初始化(按内存顺序)
        int arr2[2][3] = {1, 2, 3, 4, 5, 6};
        // 等价于上面的arr1
        
        // 3. 部分初始化 - 只初始化前几行
        int arr3[3][4] = {
            {1, 2},           // 第0行:1,2,0,0
            {3, 4, 5}         // 第1行:3,4,5,0  
            // 第2行全部为0
        };
        
        // 4. 部分初始化 - 只初始化前几个元素
        int arr4[2][3] = {1, 2, 3, 4};
        // 等价于 {{1,2,3},{4,0,0}}
        
        // 5. 全部初始化为0
        int arr5[2][3] = {0};  // 所有元素都为0
        
        // 6. 省略行数,自动推断(列数必须指定)
        int arr6[][3] = {
            {1, 2, 3},
            {4, 5, 6},
            {7, 8, 9}
        };  // 编译器自动推断行数为3
        
        // 验证初始化结果
        cout << "=== 部分初始化示例(arr3) ===" << endl;
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 4; j++) {
                cout << arr3[i][j] << "\t";
            }
            cout << endl;
        }
        // 输出:
        // 1    2    0    0
        // 3    4    5    0  
        // 0    0    0    0
        
        return 0;
    }

  4. 访问元素

    • 使用双下标:数组名[行索引][列索引]
    • 行索引范围:0 到 (行数-1)
    • 列索引范围:0 到 (列数-1)
    • 不进行边界检查,越界访问会导致未定义行为
  5. 数组名的含义

    • 数组名代表第一行的地址(即&数组名[0]
    • sizeof(数组名) 返回整个二维数组的总字节数
c++ 复制代码
#include <iostream>
using namespace std;

int main() {
    // 1. 声明并初始化二维数组
    int matrix[3][4] = {
        {1, 2, 3, 4},    // 第0行
        {5, 6, 7, 8},    // 第1行  
        {9, 10, 11, 12}  // 第2行
    };
    
    // 2. 遍历并输出二维数组
    cout << "=== 二维数组遍历 ===" << endl;
    for (int i = 0; i < 3; i++) {      // 行循环
        for (int j = 0; j < 4; j++) {  // 列循环
            cout << matrix[i][j] << "\t";
        }
        cout << endl;  // 每行结束后换行
    }
    
    // 3. 访问特定元素
    cout << "\nmatrix[1][2] = " << matrix[1][2] << endl;  // 输出7
    
    // 4. 数组大小信息
    cout << "总大小: " << sizeof(matrix) << " 字节" << endl;
    cout << "每行大小: " << sizeof(matrix[0]) << " 字节" << endl;
    cout << "元素类型大小: " << sizeof(matrix[0][0]) << " 字节" << endl;
    cout << "总元素个数: " << (sizeof(matrix) / sizeof(matrix[0][0])) << endl;
    
    return 0;
}

函数

  1. 函数的定义
c++ 复制代码
返回类型 函数名(参数列表) {
    // 函数体(具体实现代码)
    [return 表达式;]  // 如果返回类型不是void,则需要return语句
}
  1. 函数的调用
  • 语法:函数名(实际参数列表);
c++ 复制代码
#include <iostream>
using namespace std;

// 函数定义
int add(int a, int b) {
    return a + b;
}

void printResult(int result) {
    cout << "计算结果: " << result << endl;
}

int main() {
    int x = 5, y = 3;
    
    // 函数调用示例
    int sum = add(x, y);           // 调用add函数,实参是变量x和y
    printResult(sum);              // 调用printResult函数,实参是变量sum
    
    printResult(add(10, 20));      // 嵌套调用:add的返回值作为printResult的参数
    
    printResult(add(x, 7));        // 实参可以是变量和常量的组合
    
    return 0;
}
  1. 函数的类别
  • 无参无返回值 (void function())
    1. 特点:不接收任何输入,也不返回结果
    2. 用途:执行固定操作,如显示菜单、打印信息
c++ 复制代码
void showMenu() {
    cout << "=== 主菜单 ===" << endl;
    cout << "1. 开始游戏" << endl;
    cout << "2. 退出游戏" << endl;
}
  • 有参无返回值 (void function(parameters))
    • 特点:接收输入参数,但不返回结果
    • 用途:根据输入执行操作,如打印格式化信息
c++ 复制代码
void printSum(int a, int b) {
    cout << a << " + " << b << " = " << (a + b) << endl;
}
  • 无参有返回值 (return_type function())
    • 特点:不接收输入,但返回一个计算结果
    • 用途:获取系统状态、生成随机数等
c++ 复制代码
int getRandomNumber() {
    return rand() % 100 + 1;  // 返回1-100的随机数
}
  • 有参有返回值 (return_type function(parameters))

    特点:接收输入参数,并返回计算结果

    用途:最常用的函数类型,进行数据处理和计算

c++ 复制代码
int add(int a, int b) {
    return a + b;  // 根据输入参数计算并返回结果
}

案例

c++ 复制代码
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

// 1. 无参无返回值
void showMenu() {
    cout << "=== 计算器 ===" << endl;
    cout << "1. 加法" << endl;
    cout << "2. 退出" << endl;
}

// 2. 有参无返回值
void printResult(int a, int b, int result) {
    cout << a << " + " << b << " = " << result << endl;
}

// 3. 无参有返回值  
int getRandomNumber() {
    return rand() % 10 + 1;  // 返回1-10的随机数
}

// 4. 有参有返回值
int add(int a, int b) {
    return a + b;
}

int main() {
    srand(time(0));
    
    // 测试四种函数类型
    showMenu();                    // 无参无返
    
    int num1 = getRandomNumber();  // 无参有返
    int num2 = getRandomNumber();
    
    int sum = add(num1, num2);     // 有参有返
    printResult(num1, num2, sum);  // 有参无返
    
    return 0;
}
  1. 函数的分文件编写

创建.h后缀名的头文件,创建.cpp后缀名的源文件,头文件中写函数声明,源文件中写函数定义

头文件(.h 或 .hpp)

复制代码
1. 包含函数声明(函数原型)

	2. 使用    `#ifndef`/`#define`/`#endif` 防止重复包含(头文件保护)

	3. 通过    `#include` 在其他文件中引用

源文件(.cpp)

​ 1. 包含函数的具体实现(定义)

​ 2. 实现头文件中声明的函数

主文件(main.cpp)

​ 1. 包含 main() 函数

​ 2. 引用头文件来使用其他文件中的函数

指针

  • 指针的作用:指针间接访问内存

    复制代码
      **指针是C++中一种特殊的变量,用于存储另一个变量的内存地址**
  • 语法

    数据类型* 指针变量名;

  • 指针初始化

    数据类型* 指针名 = &变量名; -------将变量的地址赋值给指针

  • &取地址

    取地址运算符(&) &变量名; ------获取变量的内存地址

  • 解引用运算符 (*) *指针名 -------访问指针所指向地址中的值

  • 指针所占内存空间

    1. 大小固定
      • 在同一系统上,所有类型指针的大小都相同
      • 与指向 intdoublechar 等无关
    2. 系统依赖
      • 32位系统 :指针占 4字节(32位 = 4字节)
      • 64位系统 :指针占 8字节(64位 = 8字节)
    3. 使用 sizeof
      • sizeof(指针变量)sizeof(数据类型*) 可获取指针大小
c++ 复制代码
#include <iostream>
using namespace std;

int main() {
    int value = 42;
    
    // 1. 指针声明
    int* ptr;
    
    // 2. 指针初始化(使用取地址符&)
    ptr = &value;
    
    // 3. 解引用(使用*获取指向的值)
    cout << "value的值: " << value << endl;
    cout << "ptr指向的值: " << *ptr << endl;
    cout << "value的地址: " << &value << endl;
    cout << "ptr存储的地址: " << ptr << endl;
    
    // 4. 通过指针修改值
    *ptr = 100;
    cout << "修改后value: " << value << endl;
    
    // 5. 空指针
    ptr = nullptr;  // 安全的空指针
    
    return 0;
}

空指针指向的内存,不允许访问,访问空指针所指向的内存是非法的

  1. 空指针的本质
    • 值为 nullptr(或 NULL0
    • 不指向任何有效的内存位置
    • 是一种安全的"无指向"状态
常量指针(Pointer to const)
  • 语法const 数据类型* 指针名数据类型 const* 指针名
  • 含义 :指针指向的数据不能修改,但指针本身可以指向其他地址
  • 记忆法:"指向常量的指针"
c++ 复制代码
int a = 10, b = 20;
const int* ptr = &a;  // ptr指向常量整数

// ✅ 允许:改变指针指向
ptr = &b;  // ptr现在指向b

// ❌ 禁止:修改指针指向的数据
// *ptr = 30;  // 错误!不能通过ptr修改数据
指针常量(Const pointer)
  • 语法数据类型* const 指针名
  • 含义 :指针本身是常量,指向的地址不能改变,但可以修改指向的数据
  • 记忆法:"常量的指针"
c++ 复制代码
int a = 10, b = 20;
int* const ptr = &a;  // ptr是一个常量指针,初始化指向a

// ✅ 允许:修改指针指向的数据
*ptr = 15;  // a的值变为15

// ❌ 禁止:改变指针指向
// ptr = &b;  // 错误!ptr是常量,不能重新赋值
常量指针常量(完全常量)
  • 语法const 数据类型* const 指针名
  • 含义:既不能改变指向的地址,也不能修改指向的数据
c++ 复制代码
int a = 10, b = 20;
const int* const ptr = &a;

// ❌ 都不允许
// *ptr = 20;   // 错误!不能修改数据
// ptr = &b;    // 错误!不能改变指向

口诀

  • const* 左边:数据常量(指针可变)

  • const* 右边:指针常量(数据可变)

  • const两边:都是常量

  • **指针和数组 **

    1. 数组名的本质
      • 数组名是一个指向首元素的指针常量
      • arr 等价于 &arr[0]
      • 不能修改数组名的指向(因为是常量)
    2. 指针算术
      • 指针加减整数会按指向类型的大小移动
      • ptr + 1 移动 sizeof(类型) 个字节
    • sizeof(arr) 返回整个数组的字节数
    • sizeof(ptr) 返回指针变量的大小
c++ 复制代码
#include <iostream>
using namespace std;

int main() {
    int arr[5] = {10, 20, 30, 40, 50};
    
    // 1. 数组名作为指针
    cout << "arr = " << arr << endl;           // 数组首地址
    cout << "&arr[0] = " << &arr[0] << endl;   // 首元素地址
    cout << "*arr = " << *arr << endl;         // 10(首元素值)
    
    // 2. 指针指向数组
    int* ptr = arr;  // 等价于 int* ptr = &arr[0];
    
    // 3. 两种访问方式等价性
    cout << "\n=== 访问方式对比 ===" << endl;
    for (int i = 0; i < 5; i++) {
        cout << "arr[" << i << "] = " << arr[i] 
             << ", *(arr+" << i << ") = " << *(arr + i)
             << ", *(ptr+" << i << ") = " << *(ptr + i) << endl;
    }
    
    // 4. 指针遍历
    cout << "\n=== 指针遍历 ===" << endl;
    for (int* p = arr; p < arr + 5; p++) {
        cout << *p << " ";
    }
    cout << endl;
    
    // 5. 重要区别
    int* dynamicArr = new int[3]{1, 2, 3};
    cout << "sizeof(arr) = " << sizeof(arr) << endl;      // 整个数组大小
    cout << "sizeof(ptr) = " << sizeof(ptr) << endl;      // 指针大小
    cout << "sizeof(dynamicArr) = " << sizeof(dynamicArr) << endl; // 指针大小
    
    delete[] dynamicArr;
    return 0;
}
  • 指针和函数

    1. 指针作为函数参数
    • 概念:将指针作为参数传递给函数
    • 优点 :
      • 避免大数据的复制开销

      • 实现函数间的双向通信(修改原数据)

      • 处理动态分配的内存

结构体

  1. 结构体的定义
c++ 复制代码
struct 结构体名 {
    数据类型 成员1;
    数据类型 成员2;
    // ...
};
  1. 结构体数组

  2. 结构体指针

  3. 结构体嵌套结构体

  4. 结构体做函数参数

  5. const使用场景

  6. 结构体案例

通讯管理系统案例

内存四区

内存分区模型:代码区、全局区、栈区、堆区

代码区;只读、共享

全局区:全局变量和静态变量(static)/常量(字符串常量,const修饰的全局变量)

栈区的注意事项:不要返回局部变量的地址、栈区的数据在函数执行完成后自动释放

堆区:

new 数据类型 new返回的是该数据类型的指针;

释放数据delete 释放数组 delete [ ]

c++ 复制代码
#include <iostream>
using namespace std;

int main() {
    // --- 栈区示例 ---
    int stackVar = 50;  // 栈区,函数结束自动释放
    
    // --- 堆区示例 ---
    int* heapPtr = new int(100);      // 堆区分配
    int* heapArray = new int[5]{1,2,3,4,5};  // 堆区分配数组
    
    cout << "*heapPtr = " << *heapPtr << endl;
    
    // 使用完必须释放
    delete heapPtr;        // 释放单个int
    delete[] heapArray;    // 释放数组
    
    // 避免悬空指针
    heapPtr = nullptr;
    heapArray = nullptr;
    
    return 0;
}

引用

  1. 引用的作用

    替代指针实现引用传递

    语法:数据类型 &别名 = 原名;

  2. 引用的注意事项

    必须初始化:引用在声明时就必须绑定到一个对象

    绑定后不可更改:引用一旦初始化,就不能再指向其他对象

    绑定对象必须存在:不能引用不存在的变量(如已销毁的局部变量)

  3. 引用做函数参数

    c++ 复制代码
    返回类型 函数名(类型& 参数名) {
        // 函数体
    }
  4. 引用做函数返回值(函数调用做左值)

  5. 引用的本质是指针常量

  6. 常量引用主要用来修饰形参

进阶知识

函数高级

函数的默认参数(函数声明有默认参数,函数实现就不能有默认参数)

从右向左原则:默认参数必须从右向左依次定义

只能在声明中指定:通常在头文件中声明时设置默认值

不能重复指定:定义时不能再写默认值

函数重载(函数的返回值不可以作为函数重载的条件)

​ 允许在同一作用域内定义多个同名函数,只要它们的参数列表不同

满足:同一个作用域、函数名称相同、函数参数类型不同或顺序不同或个数不同

重载的条件

函数重载必须满足以下至少一个条件:

条件 示例
参数个数不同 func() vs func(int a)
参数类型不同 func(int a) vs func(double a)
参数顺序不同 func(int, double) vs func(double, int)

类和对象

C++面向对象的三大特性:封装、继承、多态

封装
  1. 什么是封装
  • 将相关的数据(属性)和函数(方法)组织在一个类中
  • 隐藏对象的内部实现细节
  • 通过公共接口与外界交互
  1. 封装的好处
  • 安全性:防止外部直接修改内部数据
  • 易维护性:内部实现可以改变而不影响外部代码
  • 复用性:封装好的类可以被多次使用
  • 简化使用:用户只需了解公共接口

类(class)

c++ 复制代码
class 类名 {
private:    // 私有成员(默认)
    // 数据成员(属性)
    // 成员函数
protected:  // 保护成员
    // ...
public:     // 公有成员
    // 成员函数(接口)
};
  1. 访问控制
    • private:只能在类内部访问(默认)
    • public:可以在任何地方访问
    • protected:在类内部和派生类中访问
  2. 成员组成
    • 数据成员:描述对象的属性
    • 成员函数:描述对象的行为
  3. 对象创建
    • 类名 对象名;
    • 对象通过.操作符访问公有成员

实例化

类中的属性和行为统一称为成员

struct和class的区别

默认的访问权限不同struct(public)/class(prviate)

特性 struct class
默认访问权限 public private
默认继承方式 public private
使用习惯 侧重数据组织 侧重面向对象设计

成员属性设置私有

对象的初始化和清理

1.构造函数和析构函数

​ 构造函数语法:类名(){ }

关键特征:

  • 没有返回类型 (连 void 都不能写)

  • 函数名必须与类名完全相同

  • 在创建对象时自动调用

    构造函数的特点

特性 说明
无返回值 不能写任何返回类型
自动调用 对象创建时自动执行,无需手动调用
只调用一次 每个对象在其生命周期内仅调用一次
可重载 可以有多个构造函数(参数不同)
可带参数 支持参数初始化成员变量
c++ 复制代码
#include <iostream>
using namespace std;

class Timer {
public:
    // 构造函数:开始计时
    Timer() {
        cout << "计时开始..." << endl;
    }
    
    // 析构函数:结束计时
    ~Timer() {
        cout << "计时结束!" << endl;
        cout << "任务完成!" << endl;
    }
};

void doWork() {
    Timer t;  // 创建对象,自动开始计时
    
    // 模拟做一些工作
    cout << "正在处理数据..." << endl;
    cout << "正在保存文件..." << endl;
    cout << "正在清理缓存..." << endl;
    
    // 函数结束时,t的析构函数自动被调用
}

int main() {
    cout << "程序开始" << endl;
    
    doWork();  // 调用函数
    
    cout << "程序结束" << endl;
    return 0;
}

​ 析构函数:~类名(){ }

析构函数的核心特点

特性 说明
没有返回值 不能写任何返回类型(包括void)
无参数 不能有任何参数(包括void)
自动调用 对象销毁时自动执行
只调用一次 每个对象在其生命周期内仅调用一次
不能重载 一个类只能有一个析构函数
c++ 复制代码
class 类名 {
public:
    // 构造函数 - 没有返回值,名字和类一样
    类名() {
        // 对象创建时自动执行
    }
    
    // 析构函数 - 名字前面加~
    ~类名() {
        // 对象销毁时自动执行
    }
};

2.构造函数的分类及调用

构造函数的分类:

  1. 按参数分类
类型 示例
无参构造 Person() { }
有参构造 Person(string name, int age) { }
  1. 按功能分类
类型 说明
普通构造 包括无参和有参构造
拷贝构造 Person(const Person& p) { }

拷贝构造函数:

c++ 复制代码
#include <iostream>
#include <string>
using namespace std;

class Dog {
public:
    string name;
    
    Dog(string n) : name(n) {
        cout << "创建: " << name << endl;
    }
    
    // 拷贝构造函数
    Dog(const Dog& other) {
        name = "copy_of_" + other.name;
        cout << "复制: " << other.name << " → " << name << endl;
    }
};

int main() {
    Dog dog1("旺财");           // 普通构造
    
    Dog dog2(dog1);             // 调用拷贝构造
    // 输出: 复制: 旺财 → copy_of_旺财
    
    Dog dog3 = dog1;            // 也调用拷贝构造
    // 输出: 复制: 旺财 → copy_of_旺财
    
    return 0;
}

注意事项:调用默认构造函数,不要加(),会被认为是一个函数的声明

Person p; // ✅ 调用无参构造,创建对象

Person p( ); // ❌ 这是一个函数声明!不是创建对象

拷贝构造函数调用时机:

1.使用一个已经创建完毕的对象来初始化一个新对象

2.值传递的方式给函数参数传值

3.值方式返回局部对象

c++ 复制代码
class Person {
public:
    // 拷贝构造函数
    Person(const Person& p) {
        cout << "拷贝构造函数被调用" << endl;
    }
};

int main() {
    Person p1;
    
    // 1. 用已创建的对象初始化新对象
    Person p2(p1);        // ✅
    Person p3 = p1;       // ✅
    
    // 2. 值传递给函数参数
    void func(Person p);  // 传参时调用拷贝构造
    func(p1);
    
    // 3. 值方式返回局部对象
    Person create() {
        Person temp;
        return temp;  // 返回时可能调用拷贝构造
    }
    
    return 0;
}

构造函数调用规则:创建一个类,编译器会给每个类都添加至少3个函数

分别是默认构造函数默认析构函数拷贝构造(值拷贝)

如果用户定义有参构造函数,c++不提供默认无参构造,会提供默认拷贝构造

如果用户定义拷贝构造函数,c++不会在提供其他构造函数

3. 深拷贝与浅拷贝

4.初始化列表

5.类对象作为成员

6.静态成员

7.对象模型和this指针

8.友元

9.运算符重载

继承
多态

提高知识

模版

C++的另一种编程思想称为泛型编程,主要利用的技术就是模版;

C++提供两种模版机制:函数模版类模版

模版的语法:

c++ 复制代码
template<typename T>
函数声明或定义

解释:
template ---声明创建模版
typename ---表明其后面的符号是一种数据类型,可以用class代替
T ---通用的数据类型,通常为大写字母

注意事项:

自动类型推导,必须推导出一致的数据类型T,才可以使用

模版必须要确定出T的数据类型,才可以使用

普通函数与函数模版区别:

普通函数调用可以发生隐式类型转换,函数模板调用不会发生隐式类型转换

如果利用显示指定类型的方式,可以发生隐式类型转换

普通函数与函数模版的调用规则:

如果函数模版和普通函数都可以实现,优先调用普通函数

可以通过空模版参数列表来强制调用函数模版

函数模版也可以发生重载

如果函数模版可以产生更好的匹配,优先调用函数模版

类模版

语法:

c++ 复制代码
template <typename T>
类

解释:
template  ---声明创建末模板
typename ---表明其后面的符号是一种数据类型,可以用class代替
T   ---通用的数据类型

STL(Standard Template Library)

STL基本概念

STL从广义上分为容器(container)算法(algorithm)迭代器(iterator)

算法和容器之间通过迭代器进行无缝连接

STL六大组件

容器、算法、迭代器、仿函数、适配器(配接器)、空间配置器

1.容器:各种数据结构,如vector、list、deque、set、map等,用来存放数据

2.算法:各种常用的算法

3.迭代器:扮演了容器与算法之间的胶合剂

4.仿函数:行为类似函数

5.适配器:一种用来修饰容器或者仿函数或迭代器接口的东西

6.空间配置器:负责空间的配置与管理

容器:

STL容器就是将运用最广泛的一些数据结构实现出来

常用的数据结构:数组、链表、树、队列、集合、映射表等

这些容器分为序列式容器和关联式容器:

​ 序列式容器:强调值的排序,序列式容器中的每个元素均有固定的关系

​ 关联式容器:二叉树结构,各元素之间没有严格的物理上的顺序关系

算法(ALgorithms)

算法分为:质变算法和非质变算法

​ 质变算法:是指运算过程中会更改区间内元素的内容,例如拷贝、替换、删除等等

​ 非质变算法:是指运算过程中不会更改区间内元素内容,例如查找、计数、遍历、寻找极值等

迭代器:

提供一种方法,使之能够依寻访问某个日期所含的各个元素,而有又无需暴露该容器的内部表示方式

种类:

种类 功能 支持运算
输入迭代器 对数据的只读访问 只读,,++、==、!=
输出迭代器 对数据的只写访问 只写,++
前向迭代器 读写操作,并向前推进迭代器 读写,++、==、!=
双向迭代器 读写操作,并能向前和向后操作 读写,++,--
随机访问迭代器 读写操作,可以以跳跃的方式访问任意数据 读写,++,--,[n],-n、<、<=、>、>=

容器算法迭代器初识

vector存放内置数据类型

容器: vector

算法: for_each

迭代器: vector<int>::iterator

Java 程序设计语言

Python程序设计语言

相关推荐
WaibiJiangzhi5 小时前
《动手学深度学习》学习笔记——02深度学习介绍
笔记·学习
勇敢di牛牛6 小时前
【css】快速上手Flexbox布局(理论讲解+实战)
前端·css3
2501_938780286 小时前
服务器 Web 安全:Nginx 配置 X-Frame-Options 与 CSP 头,防御 XSS 与点击劫持
服务器·前端·安全
岑梓铭6 小时前
《考研408数据结构》第六章(5.4树和森林)复习笔记
数据结构·笔记·考研·算法·408·ds
IT_陈寒6 小时前
Java 17 新特性实战:这5个隐藏功能让你的代码效率提升50%
前端·人工智能·后端
眠りたいです6 小时前
基于脚手架微服务的视频点播系统-脚手架开发部分-FFmpeg,Etcd-SDK的简单使用与二次封装
c++·微服务·云原生·架构·ffmpeg·etcd
艾小码6 小时前
2025年组件化开发这样做,效率提升300%
前端·javascript
驭风少年君13 小时前
《搭建属于自己的网站之网页前端学习》基础入门
前端·学习
刘一说14 小时前
深入理解 Spring Boot 嵌入式 Web 容器:从原理到性能调优
前端·spring boot·firefox