C++ 核心基础:数字、数组、字符串、指针与引用详解
- 1. C++ 基础语法
- 1.1 标识符与保留字
- 1.2 数据类型概述
- 1.3 基本输入输出
- 2.1 基本整数类型(int、short、long、long long)
- 2.2 无符号整数类型(unsigned int、unsigned short、unsigned long、unsigned long long)
- 2.3 整数类型选择与应用场景
- 3.1 单精度浮点数(`float`)
- 3.2 双精度浮点数(`double`)
- 3.3 扩展精度浮点数(`long double`)
- 4.1 一维数组定义与操作
- 4.1.1 定义与初始化
- 4.1.2 访问与修改元素
- 4.1.3 数组的大小
- 4.1.4 应用场景
- 4.2 多维数组定义与操作
- 4.2.1 二维数组
- 4.2.2 访问与修改元素
- 4.2.3 数组的大小
- 4.2.4 应用场景
- 4.2.5 高维数组
- 4.3 动态数组与内存管理
- 4.3.1 动态数组的创建
- 4.3.2 动态数组的使用
- 4.3.3 内存管理
- 4.3.4 应用场景
- 4.3.5 注意事项
- 5.1 字符数组与 `std::string`
- 5.2 字符串操作函数与方法
- 5.3 字符串处理技巧
- 6.1 指针基本概念与操作
- 6.1.1 指针的定义
- 6.1.2 获取变量的地址
- 6.1.3 通过指针访问变量
- 6.1.4 指针的初始化
- 6.1.5 指针的应用
- 6.2 指针与数组关系
- 6.2.1 数组名作为指针
- 6.2.2 指针与数组的遍历
- 6.2.3 指针与多维数组
- 6.2.4 指针与函数参数
- 6.2.5 指针与动态数组
- 6.3 指针在函数参数与动态内存中的应用
- 6.3.1 函数参数传递
- 6.3.2 动态内存分配
- 6.3.3 注意事项
- 7.1 引用基本概念与操作
- 7.2 引用与指针的区别
- 语法区别
- 语义区别
- 使用场景
- 安全性
- 7.3 引用在函数参数与返回值中的应用
- 函数参数传递
- 函数返回值
- 注意事项
1. C++ 基础语法
1.1 标识符与保留字
在 C++ 中,标识符用于命名变量、函数、类等。一个有效的标识符必须以字母(A-Z 或 a-z)或下划线 _
开头,后续可以包含字母、数字(0-9)和下划线。标识符是区分大小写的,这意味着 Variable
和 variable
是两个不同的标识符。例如,int myVariable = 10;
中的 myVariable
是一个合法的标识符。
C++ 中有一些保留字,这些保留字不能用作标识符,因为它们在语言中有特殊的含义。例如,int
、class
、return
等都是保留字。使用保留字作为标识符会导致编译错误。C++ 标准中定义了大约 65 个保留字,这些保留字在不同的上下文中有不同的用途,如控制流程(if
、else
)、数据类型(int
、float
)和函数定义(return
)等。
1.2 数据类型概述
C++ 提供了丰富的数据类型,这些数据类型可以分为基本数据类型和复合数据类型。基本数据类型包括整数类型、浮点类型、字符类型和布尔类型,而复合数据类型包括数组、结构体、类等。
- 整数类型:用于存储没有小数部分的数值。C++ 提供了多种整数类型,如
int
、short
、long
和long long
,它们的存储大小和取值范围各不相同。例如,int
通常占用 4 个字节,取值范围为 ([-2^{31}, 2^{31}-1],而long long
占用 8 个字节,取值范围为 ([-2^{63}, 2^{63}-1]。选择合适的整数类型可以优化内存使用和程序性能。 - 浮点类型:用于存储包含小数部分的数值。C++ 提供了
float
、double
和long double
三种浮点类型,它们的精度和存储大小不同。float
通常占用 4 个字节,有效数字为 7 位;double
占用 8 个字节,有效数字为 15-16 位;long double
的精度更高,占用字节数根据实现而变化。在科学计算和工程应用中,通常使用double
类型以获得更高的精度。 - 字符类型:用于存储单个字符,如字母、数字和符号。C++ 中的字符类型是
char
,它占用 1 个字节,可以存储 ASCII 字符集中的字符。例如,char c = 'A';
定义了一个字符变量c
并赋值为大写字母 A。 - 布尔类型:用于存储逻辑值,只有两个可能的值:
true
和false
。布尔类型在条件判断和逻辑运算中非常有用。例如,bool isTrue = true;
定义了一个布尔变量isTrue
并赋值为true
。
1.3 基本输入输出
C++ 提供了强大的输入输出功能,主要通过标准输入输出流 cin
和 cout
来实现。这些流对象与 C++ 标准库中的输入输出操作符 <<
和 >>
配合使用,可以方便地进行数据的输入和输出。
- 输出操作:使用
cout
和<<
操作符可以将数据输出到标准输出设备(通常是屏幕)。例如,std::cout << "Hello, World!" << std::endl;
会在屏幕上输出 “Hello, World!”,并换行。std::endl
是一个特殊的操纵符,用于在输出后添加一个换行符,并刷新输出缓冲区。 - 输入操作:使用
cin
和>>
操作符可以从标准输入设备(通常是键盘)读取数据。例如,int num; std::cin >> num;
会从键盘读取一个整数并存储到变量num
中。cin
可以读取多种类型的数据,包括整数、浮点数和字符。 - 格式化输入输出:C++ 提供了一些操纵符,如
std::setw
、std::setprecision
等,用于控制输入输出的格式。例如,std::cout << std::setw(10) << num << std::endl;
会将变量num
的输出宽度设置为 10 个字符,不足的部分用空格填充。std::setprecision(2)
可以设置浮点数的输出精度为小数点后两位。
C++ 的输入输出功能不仅简单易用,而且具有很强的灵活性和可扩展性。通过标准库中的输入输出流和操纵符,可以方便地实现各种复杂的输入输出需求。# 2. 整数类型
2.1 基本整数类型(int、short、long、long long)
C++ 中的基本整数类型包括 int
、short
、long
和 long long
,它们的存储大小和取值范围各不相同,适用于不同的应用场景。
int
:这是最常用的整数类型,通常占用 4 个字节(32 位),取值范围为 ([-2^{31}, 2^{31}-1],即 ([-2147483648, 2147483647])。它适用于大多数需要整数的场景,如计数器、索引等。例如:int age = 25;
short
:短整数类型,通常占用 2 个字节(16 位),取值范围为 ([-2^{15}, 2^{15}-1],即 ([-32768, 32767])。它适用于需要节省内存的场景,尤其是在处理大量数据时。例如:short count = 100;
long
:长整数类型,通常占用 4 个字节(32 位),在 64 位系统中可能为 8 个字节(64 位),取值范围为 ([-2^{31}, 2^{31}-1] 或 ([-2^{63}, 2^{63}-1])。它用于存储比int
更大的整数。例如:long distance = 1000000;
long long
:更长的整数类型,占用 8 个字节(64 位),取值范围为 ([-2^{63}, 2^{63}-1],即 ([-9223372036854775808, 9223372036854775807])。它适合处理非常大的整数,例如在金融计算或大数运算中。例如:long long bigNumber = 1234567890123456789;
2.2 无符号整数类型(unsigned int、unsigned short、unsigned long、unsigned long long)
无符号整数类型与基本整数类型的主要区别在于它们只能表示非负数,因此其取值范围是正数和零,且范围更大。
unsigned int
:无符号整数类型,通常占用 4 个字节(32 位),取值范围为 ([0, 2^{32}-1],即 ([0, 4294967295])。它适用于需要表示非负数的场景,如数组索引、计数器等。例如:unsigned int index = 1000000000;
unsigned short
:无符号短整数类型,通常占用 2 个字节(16 位),取值范围为 ([0, 2^{16}-1],即 ([0, 65535])。它适用于需要节省内存且只处理非负数的场景。例如:unsigned short port = 8080;
unsigned long
:无符号长整数类型,通常占用 4 个字节(32 位),在 64 位系统中可能为 8 个字节(64 位),取值范围为 ([0, 2^{32}-1] 或 ([0, 2^{64}-1])。它用于存储比unsigned int
更大的非负整数。例如:unsigned long fileSize = 4294967295;
unsigned long long
:无符号超长整数类型,占用 8 个字节(64 位),取值范围为 ([0, 2^{64}-1],即 ([0, 18446744073709551615])。它适合处理非常大的非负整数,例如在大文件处理或高精度计算中。例如:unsigned long long bigFileSize = 18446744073709551615;
2.3 整数类型选择与应用场景
选择合适的整数类型可以优化内存使用和程序性能,同时避免溢出和数据丢失等问题。以下是一些选择整数类型的建议和常见应用场景:
- 通用场景:对于大多数需要整数的场景,
int
是首选类型。它在大多数平台上占用 4 个字节,取值范围足够大,适用于计数器、索引、循环变量等。 - 节省内存:当需要处理大量数据且数据范围较小时,
short
或unsigned short
是更好的选择。例如,在嵌入式系统或内存受限的环境中,short
可以节省内存。 - 大整数处理:当需要处理非常大的整数时,
long long
或unsigned long long
是合适的选择。例如,在金融计算、大文件处理或高精度数学模型中,long long
可以提供足够的范围。 - 非负数场景:当变量的值总是非负数时,使用无符号整数类型可以提供更大的范围。例如,数组索引、文件大小、端口号等通常使用无符号整数类型。
- 跨平台兼容性:在跨平台开发中,应避免使用依赖于平台的整数类型(如
long
),而是使用固定宽度的整数类型(如int32_t
、int64_t
),这些类型在不同平台上具有相同的大小和范围。# 3. 浮点类型
浮点类型用于存储包含小数部分的数值,C++ 提供了三种主要的浮点类型:float
、double
和long double
。它们在存储大小、精度和适用场景上各有不同。以下将从不同角度对这三种浮点类型进行详细分析。
3.1 单精度浮点数(float
)
float
是单精度浮点数类型,通常占用 4 个字节(32 位),其有效数字为 7 位。它适用于对精度要求不高但需要快速计算的场景。
- 存储格式:
float
类型的存储格式遵循 IEEE 754 标准,分为符号位、指数位和尾数位。其中,符号位占用 1 位,指数位占用 8 位,尾数位占用 23 位。这种格式使得float
能够表示非常大或非常小的数值,但精度相对较低。 - 取值范围:
float
的取值范围大约为 ([-3.4 \times 10^{38}, 3.4 \times 10^{38}]),但其有效数字仅为 7 位,因此在表示较大或较小的数值时,可能会出现精度损失。 - 应用场景:
float
适用于对精度要求不高但需要快速计算的场景,例如实时图形渲染、简单的物理模拟等。在这些场景中,计算速度比精度更为重要,因此float
是一个合适的选择。
3.2 双精度浮点数(double
)
double
是双精度浮点数类型,通常占用 8 个字节(64 位),其有效数字为 15-16 位。它适用于需要更高精度的场景,例如科学计算和工程应用。
- 存储格式:
double
类型的存储格式同样遵循 IEEE 754 标准,分为符号位、指数位和尾数位。其中,符号位占用 1 位,指数位占用 11 位,尾数位占用 52 位。这种格式使得double
能够表示更大范围的数值,并且具有更高的精度。 - 取值范围:
double
的取值范围大约为 ([-1.7 \times 10^{308}, 1.7 \times 10^{308}]),其有效数字为 15-16 位,因此在表示较大或较小的数值时,能够保持较高的精度。 - 应用场景:
double
适用于需要更高精度的场景,例如科学计算、工程应用、金融计算等。在这些场景中,计算结果的精度至关重要,因此double
是一个更可靠的选择。例如,在计算复杂的数学模型、进行高精度的数值分析时,double
能够提供更准确的结果。
3.3 扩展精度浮点数(long double
)
long double
是扩展精度浮点数类型,其占用的字节数根据实现而变化,通常为 12 或 16 个字节,精度更高。它用于需要极高精度的计算,例如高精度的数学模型。
- 存储格式:
long double
的存储格式在不同的实现中可能有所不同,但通常遵循 IEEE 754 标准的扩展精度格式。它包含更多的尾数位和指数位,因此能够表示更大范围的数值,并且具有更高的精度。 - 取值范围:
long double
的取值范围和精度取决于具体的实现,但通常比double
更高。例如,在某些实现中,long double
的取值范围可以达到 ([-1.7 \times 10^{4932}, 1.7 \times 10^{4932}]),有效数字可以达到 18-19 位。 - 应用场景:
long double
适用于需要极高精度的计算场景,例如高精度的数学模型、复杂的物理模拟等。在这些场景中,计算结果的精度要求极高,因此long double
是一个必要的选择。然而,由于long double
的计算速度相对较慢,并且占用更多的内存,因此在实际应用中需要权衡精度和性能之间的关系。
在选择浮点类型时,需要根据具体的应用场景和精度要求进行权衡。如果对精度要求不高但需要快速计算,可以选择 float
;如果需要更高的精度,可以选择 double
;如果需要极高精度的计算,可以选择 long double
。# 4. 数组
数组是一种基本的数据结构,用于存储相同类型的多个元素。在 C++ 中,数组的大小在定义时必须确定,且数组的大小在运行时不可变。数组的元素在内存中是连续存储的,这使得数组在访问元素时非常高效。
4.1 一维数组定义与操作
一维数组是最简单的数组形式,它存储的是一系列相同类型的元素。
4.1.1 定义与初始化
一维数组可以通过指定数组的类型、名称和大小来定义。例如:
int arr[5]; // 定义一个包含 5 个整数的数组
数组也可以在定义时直接初始化:
int arr[5] = {1, 2, 3, 4, 5}; // 定义并初始化一个包含 5 个整数的数组
如果初始化的元素个数少于数组的大小,剩余的元素将被自动初始化为 0:
int arr[5] = {1, 2}; // 剩余的元素将被初始化为 0
4.1.2 访问与修改元素
数组的元素可以通过索引访问和修改。索引从 0 开始,因此第一个元素的索引为 0,最后一个元素的索引为数组大小减 1。例如:
int value = arr[2]; // 获取数组的第三个元素
arr[2] = 10; // 修改数组的第三个元素
4.1.3 数组的大小
可以使用 sizeof
运算符来获取数组的大小(以字节为单位),并结合数组元素的大小来计算数组的长度:
int size = sizeof(arr) / sizeof(arr[0]); // 计算数组的长度
4.1.4 应用场景
一维数组常用于存储和处理一系列数据,例如学生成绩、温度记录等。它也常用于算法实现中,如排序和搜索算法。
4.2 多维数组定义与操作
多维数组是数组的扩展,它允许在多个维度上存储数据。最常见的多维数组是二维数组,但也可以定义三维甚至更高维度的数组。
4.2.1 二维数组
二维数组可以看作是一个表格,它有行和列。定义二维数组时需要指定行数和列数。例如:
int matrix[3][4]; // 定义一个 3 行 4 列的二维数组
二维数组也可以在定义时初始化:
int matrix[3][4] = {{1, 2, 3, 4},{5, 6, 7