Essential C++
Essential C++
1. 构造函数初始化语法(constructor initialization syntax)
处理多值初始化
C++支持 3 种浮点数型别
- float
- double
- extended precision:扩展精度
2. const 关键词(永恒不变)
const int max_tries = 3;
const double pi = 3.14159;
3. 指针
作用:可以通过指针间接访问内存
- 内存编号是从 0 开始记录的,一般用 十六进制数字表示
- 可以利用指针变量保存地址
指针的定义与使用
#include <iostream>
#include "swap.h"
using namespace std;
int main() {
// 1. 定义一个指针
// 指针定义语法:数据类型 * 指针变量名
int a = 10;
int* p;
// 让指针记录变量 a 的地址(&:取址符号)
p = &a;
cout << "a 的地址为:" << &a << endl; // a 的地址为:0x61fe14
cout << "指针p 为:" << p << endl; // 指针 p 为:0x61fe14 【指针记录的就是地址】
// 2. 使用指针
// 可以通过解引用的方式来找到指针指向的内存
// 指针前加 * 代表解引用,找到指针指向的内存中的数据
*p = 888;
cout << "a= :" << a << endl;
}
指针所占内存空间
指针也是一种数据类型,那么这种数据类型占用多少内存空间呢?
#include <iostream>
#include "swap.h"
using namespace std;
int main() {
// 1. 定义一个指针
// 指针定义语法:数据类型 * 指针变量名
int a = 10;
int* p = &a;
// 让指针记录变量 a 的地址(&:取址符号)
cout << "sizeof (int *) = " << sizeof(p) << endl; // 8个字节(64 位系统)
}
空指针
定义:指针变量指向内存编号为 0 的空间
用途:初始化指针变量
注意:空指针指向的内存是不可以访问的
#include <iostream>
#include "swap.h"
using namespace std;
int main() {
// 空指针
// 1. 用于给指针变量进行初始化
int * p = NULL;
// 2. 空指针是不可以进行访问的(0 ~ 255 之间的内存编号是系统占用的,因此不可访问)
*p = 100;
// 让指针记录变量 a 的地址(&:取址符号)
cout << "sizeof (int *) = " << sizeof(p) << endl; // 8个字节(64 位系统)
}
野指针
定义:指针变量指向非法的内存口空间
#include <iostream>
#include "swap.h"
using namespace std;
int main() {
// 野指针
// 在程序中,尽量避免出现野指针
int * p = (int*)0x1100;
cout << *p << endl;
}
总结:空指针和野指针都不是我们申请的空间,因此不要访问
const 修饰指针
const修饰指针 --- 常量指针(const 后面紧跟 *,那么取 * 操作就不可以了)
# 指针的指向可以修改,但是指针指向的值不可以改
const int *p = &a;
#include <iostream>
using namespace std;
int main() {
// 常量指针
int a = 10;
int b = 11;
const int* p = &a;
p = &b; // 指针的指向可以修改
cout << *p << endl;
}
指针指向的值不可以修改
总结:
const修饰常量 --- 指针常量(const 紧跟着p,那么 &p 就不能操作了)
# 指针的指向不可修改,指针指向的值可以修改
int* const p = &a
#include <iostream>
using namespace std;
int main() {
// 常量指针
int a = 10;
int b = 11;
int* const p = &a;
*p = 11; // 指针指向的值可以改
cout << *p << endl;
}
总结:
cnost 修饰指针,又修饰常量
# const 既修饰指针,又修饰常量
# 特点:指针的指向和指针指向的值都不可以修改
const int* const p = &a;
指针和数组
作用:利用指针访问数组中元素
#include <iostream>
using namespace std;
int main() {
// 常量指针
int arr[] = {1,2,3,4,5,6,7,8,9,10};
int* p = arr;
cout << "第一个元素: " << arr[0] << endl;
cout << "指针访问第一个元素: " << *p << endl; // *p ===> * 代表解引用
p++; // 本身就是 int 类型 指针 ===> 让指针向后偏移 4个字节
cout << "指针访问第2个元素: " << *p << endl;
}
下面使用指针来访问数组中所有元素
#include <iostream>
using namespace std;
int main() {
// 常量指针
int arr[] = {1,2,3,4,5,6,7,8,9,10};
int* p = arr;
int size = sizeof(arr) / sizeof(arr[0]);
for(int i = 0; i < size; i++){
cout << "第" << i <<"个元素: " << *p << endl;
p++;
}
}
指针和函数
作用:利用指针作函数参数,可以修改实参的值
地址传递
void swap2(int* a, int* b){
int temp = *a;
*a = *b;
*b = temp;
cout << "a = " << a << endl;
cout << "b = " << b << endl;
}
调用
#include <iostream>
#include "swap.h"
using namespace std;
int main() {
// 常量指针
int a = 1;
int b = 2;
int *p1 = &a;
int *p2 = &b;
swap2(p1, p2);
cout << "a= " << a;
cout << "b= " << b;
return 0;
}
4. 数组长度
一维数组
#include <iostream>
using namespace std;
int main()
{
int arr[5] = {10, 20, 30, 40, 50};
// 利用循环输出数组中的元素
// sizeof()函数可以返回数组所占的内存,而sizeof(a[0])返回的是数组第一个元素所占的内存
for(int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
cout << arr[i] << endl;
}
// 通过数组名称:获取数组在内存中的首地址
cout << arr << endl; // 0x61fe00
return 0;
}
数组反转:
#include <iostream>
using namespace std;
void swap(int arr[], int length){
int l = 0;
int r = length - 1; // sizeof(arr) 在函数 swap 中返回的是指针大小(通常是4或8个字节,取决于系统架构),而不是数组的大小。
while (l < r)
{
int temp = arr[l];
arr[l] = arr[r];
arr[r] = temp;
l++;
r--;
}
}
int main()
{
int arr[5] = {10, 20, 30, 40, 50};
// 利用循环输出数组中的元素
// sizeof()函数可以返回数组所占的内存,而sizeof(a[0])返回的是数组第一个元素所占的内存
int length = sizeof(arr) / sizeof(arr[0]);
for(int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
cout << arr[i] << endl;
}
swap(arr, length);
cout << "逆转后:" << endl;
for(int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
cout << arr[i] << endl;
}
// 通过数组名称:获取数组在内存中的首地址
cout << arr << endl; // 0x61fe00
return 0;
}
https://blog.csdn.net/zou_albert/article/details/107337756
冒泡排序
#include <iostream>
using namespace std;
void bubbleSort(int arr[], int len) {
for(int i = len - 1; i > 0; i--){
for(int j = 0; j < i; j++){
if (arr[j] > arr[j + 1]){
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
int main() {
int arr[5] = {40, 30, 20, 10, 50};
// 利用循环输出数组中的元素
// sizeof()函数可以返回数组所占的内存,而sizeof(a[0])返回的是数组第一个元素所占的内存
int length = sizeof(arr) / sizeof(arr[0]);
for(int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
cout << arr[i] << endl;
}
bubbleSort(arr, length);
cout << "逆转后:" << endl;
for(int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
cout << arr[i] << endl;
}
// 通过数组名称:获取数组在内存中的首地址
cout << arr << endl; // 0x61fe00
return 0;
}
二维数组
我们可以从二维数组名,得到:
- 查看二维数组所占内存空间
- 获取二维数组首地址
#include <iostream>
using namespace std;
int main() {
// 定义一个3x4的二维数组
int arr[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
cout << "二维数组大小:" << sizeof(arr) << endl;
cout << "二维数组一行大小:" << sizeof(arr[0]) << endl;
cout << "二维数组元素大小:" << sizeof(arr[0][0]) << endl;
// 获取数组的行数和列数
int rows = sizeof(arr) / sizeof(arr[0]);
int cols = sizeof(arr[0]) / sizeof(arr[0][0]);
// 遍历并打印二维数组的元素
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
cout << arr[i][j] << " ";
}
cout << endl;
}
return 0;
}
二维数组应用(考试成绩统计)
#include <iostream>
using namespace std;
int main() {
// 定义一个3x4的二维数组
int scores[3][3] = {
{100, 100, 100},
{90, 50, 100},
{60, 70, 80}
};
string names[3] = {"张三", "李四", "王五"};
// 统计每个人的总和分数
cout << "二维数组大小:" << sizeof(scores) << endl;
cout << "二维数组一行大小:" << sizeof(scores[0]) << endl;
cout << "二维数组元素大小:" << sizeof(scores[0][0]) << endl;
// 获取数组的行数和列数
int rows = sizeof(scores) / sizeof(scores[0]);
int cols = sizeof(scores[0]) / sizeof(scores[0][0]);
// 遍历并打印二维数组的元素
for (int i = 0; i < rows; ++i) {
int sum = 0;
for (int j = 0; j < cols; ++j) {
sum += scores[i][j];
}
cout << names[i] << "的总分为: " << sum << endl;
}
return 0;
}
5. 函数的分文件编写(让代码结构更加清晰)
函数的分文件编写一般有 4个 步骤:
- 创建 .h 文件 ===> 在头文件中写函数的声明
- 创建 .cpp 的源文件 ===> 在函数的实现
6. 结构体 Struct
结构体属于用户 自定义的数据类型,允许用户存储不同的数据类型
#include <iostream>
#include <string>
using namespace std;
struct Student{
string name;
int age;
int score;
} s3; // 注意结构体后面要有分号 ;
void printStudent(Student student){
cout << "姓名: " << student.name << " 年龄:" << student.age << " 分数:" << student.score << endl;
}
int main() {
// 通过学生类型创建具体学生
// 1. struct Student s1【注意:struct 关键字可以省略】
struct Student s1;
s1.name = "bjq";
s1.age = 18;
s1.score = 100;
printStudent(s1);
// 2. struct Student s2 = { ... }
struct Student s2 = {"李四", 19, 80};
printStudent(s2);
// 3. 在定义结构体时顺便创建结构体变量
s3.name = "YY";
s3.age = 20;
s3.score = 60;
printStudent(s3);
return 0;
}
结构体数组
#include <iostream>
#include <string>
using namespace std;
struct Student{
string name;
int age;
int score;
} s3; // 注意结构体后面要有分号 ;
void printStudent(Student student){
cout << "姓名: " << student.name << " 年龄:" << student.age << " 分数:" << student.score << endl;
}
int main() {
// 创建结构体数组
struct Student stuArray[3] =
{
{"张三", 18, 100},
{"李四", 28, 99},
{"王五", 38, 66},
};
int size = sizeof(stuArray) / sizeof(stuArray[0]);
for(int i = 0; i < size; i++){
Student stu = stuArray[i];
cout << "姓名:" << stu.name << "年龄:" << stu.age << "分数:" << stu.score << endl;
}
return 0;
}
结构体指针
利用操作符 -> 可以通过结构体指针访问结构体属性
#include <iostream>
#include <string>
using namespace std;
struct Student{
string name;
int age;
int score;
} s3; // 注意结构体后面要有分号 ;
void printStudent(Student student){
cout << "姓名: " << student.name << " 年龄:" << student.age << " 分数:" << student.score << endl;
}
int main() {
// 1、创建学生结构体变量
// 2、通过指针指向结构体变量
// 3、通过指针访问结构体变量中的数据
struct Student s = {"ACLQ", 18, 100};
Student * p = &s;
cout << "姓名:" << p->name << "年龄:" << p->age << "分数:" << p->score << endl;
return 0;
}
结构体嵌套结构体
#include <iostream>
#include <string>
using namespace std;
struct Student{
string name;
int age;
int score;
}; // 注意结构体后面要有分号 ;
struct Teacher{
string name;
int age;
int score;
struct Student stu;
}; // 注意结构体后面要有分号 ;
void printStudent(Student student){
cout << "姓名: " << student.name << " 年龄:" << student.age << " 分数:" << student.score << endl;
}
int main() {
// 1、创建学生结构体变量
// 2、通过指针指向结构体变量
// 3、通过指针访问结构体变量中的数据 (->)
struct Teacher teacher = {"ACLQ", 18, 100, {"stu", 18, 100}};
Teacher * p = &teacher;
cout << "姓名:" << p->name << "年龄:" << p->age << "分数:" << p->score << "的 学生姓名:" << p->stu.name << endl;
return 0;
}
结构体做函数参数
值传递
void printStudent(Student student){ // 值传递
student.age = 18;
cout << "姓名: " << student.name << " 年龄:" << student.age << " 分数:" << student.score << endl;
}
地址传递
void printStudent2(Student* student){ // 地址传递 ===> 形参影响实参
student->age = 18;
cout << "姓名: " << student->name << " 年龄:" << student->age << " 分数:" << student->score << endl;
}
#include <iostream>
#include <string>
using namespace std;
struct Student{
string name;
int age;
int score;
}; // 注意结构体后面要有分号 ;
void printStudent(Student student){ // 值传递
student.age = 18;
cout << "姓名: " << student.name << " 年龄:" << student.age << " 分数:" << student.score << endl;
}
void printStudent2(Student* student){ // 地址传递 ===> 形参影响实参
student->age = 18;
cout << "姓名: " << student->name << " 年龄:" << student->age << " 分数:" << student->score << endl;
}
int main() {
// 结构体做函数参数
// 将学生传入到一个参数中,打印学生的所有信息
// 创建结构体变量
Student s = {"BJQ", 20, 85};
printStudent(s);
cout << s.age << endl;
printStudent2(&s);
cout << s.age << endl;
return 0;
}
结构体中 const 使用场景
作用:用 const 来防止误操作