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个 步骤:

  1. 创建 .h 文件 ===> 在头文件中写函数的声明
  2. 创建 .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 来防止误操作

posted @ 2024-07-14 01:16  爱新觉罗LQ  阅读(27)  评论(0编辑  收藏  举报