C++基础从0到1入门编程(一)

系统学习C++
方便自己日后复习,错误的地方希望积极指正
参考视频:黑马程序员匠心之作|C++教程从0到1入门编程,学习编程不再难

1 第一个C程序-HelloWorld

编写一个C++程序分为四个步骤:
(1)创建项目
(2)创建文件
(3)编写代码
(4)运行程序

#include <iostream>
using namespace std;
/*
main 是一个程序的入口
每个程序有且只有一个
*/
int main()
{
    cout << "hello world" << endl; // 输出Hello world
    system("pause");
    return 0;
}

2 程序的注释

编译器不会执行注释的内容

作用:代码添加说明,方便阅读
两种格式:
(1)单行注释://
通常放在语句的上方,或者一条语句的结尾
(2)多行注释:/**/
通常放在一段代码的上方

3 变量

变量存在的意义:方便我们管理内存空间
作用:给一段指定的内存空间起名,方便操作这段内存
语法:数据类型 变量名 = 初始值;
在这里插入图片描述

#include <iostream>
using namespace std;
int main()
{
    int a = 10;
    cout << "a = " << a << endl;
    system("pause");
    return 0;
}

4 常量

作用:用于记录程序中不可更改的数据
定义常量的方式:
(1)#define 宏常量:#define 常量名 常量值
通常在文件上方定义,表示一个常量
(2)const 修饰变量:const 数据类型 常量名 = 常量值
通常在变量定义前加关键字const,修改变量为常量,不可修改

#include <iostream>
using namespace std;
#define Day 7

int main()
{
	cout << Day << endl;
	const int month = 12;
	system("pause");
	return 0;
}

5 C++常用编程关键字

作用:C++预先保留的单词(标识符)

在定义变量或者常量时,不要用关键字,否则产生歧义

在这里插入图片描述

#include <iostream>
using namespace std;

int main()
{
    int a = 10;
    // int int = 10; 错误,第二个int是关键字
    system("pause");
    return 0;
}

6 标识符命名规则

作用:C++规定给标识符(变量、常量)命名时,有一套自己的规则

  1. 标识符不能是关键字
  2. 标识符只能由字母、数字、下划线组成
  3. 第一个字符必须为字母或者下划线
  4. 标识符中字母区分大小写

给变量起名的时候,最好能够做到见名知意

7 数据类型

7.1 整型

C++规定在创建一个变量或者常量时,必须指定相应的数据类型,否则无法给变量分配内存。
数据类型存在意义:给变量分配合适的内存空间
在这里插入图片描述

#include <iostream>
using namespace std;

int main()
{
    short num1 = 10; // (-32768- 32767)
    int num2 = 10;
    long num3 = 10;
    long long num4 = 10;
    
    cout << "num1 = " << sizeof(num1) << endl; // 2
    cout << "num2 = " << sizeof(num2) << endl; // 4
    cout << "num3 = " << sizeof(num3) << endl; // 4
    cout << "num4 = " << sizeof(num4) << endl; // 8
    
    system("pause");
    return 0;
}
7.1.1 整数的书写

整数默认是十进制,一个表示十进制的数字不需要任何特殊的格式
(1)二进制
二进制由 0 和 1 两个数字组成,书写必须以0b或0B开头
(2)八进制
(3)十六进制
Tip:在C++中,不要在十进制数前面加0,会被编译器当成八进制,还有,不要随便删掉别人程序中整数前面的0,它不是多余的

#include <iostream>
using namespace std;

int main()
{
    // 十进制
    int a = 100;
    cout << a << endl; // 100
    // 二进制
    int b = 0b101; // 5
    int c = 0B1;   // 1
    cout << b << " " << c << endl;
    // 八进制(设备的权限)
    int d = 015;   // 13
    int e = -0101; // -65
    cout << d << " " << e << endl;
    // 十六进制(内存的地址)0 ~ 9 A ~ F a ~ f
    int m = 0X2A; // 42
    int n = -0XA0; // -160
    cout << m << " " << n << endl;
    return 0;
}
7.2 sizeof关键字

作用:利用sizeof关键字可以统计数据类型所占内存大小
语法:sizeof(数据类型 或者 变量)

#include <iostream>
using namespace std;
// short < int <= long <= longlong
int main()
{
    short num1 = 10;
    cout << sizeof(num1) << ' ' << sizeof(short);
    system("pause");
    return 0;
}
7.3 实型(浮点型)

作用:用于表示小数
(1)单精度 float
(2)双精度 double
区别:表示的有效数字范围不同
在这里插入图片描述

#include <iostream>
using namespace std;
// 默认情况下,输出一个小数,会显示6位有效数字
int main()
{
    float f1 = 3.1415926f; // 默认double,在后面加f 让double - > float 3.14159
    cout << f1 << endl;
    double d1 = 3.1415926;
    cout << d1 << endl;
    // float double占用的内存空间
    cout << sizeof(float) << ' ' << sizeof(double) << endl;// float:4 double:8
    // 科学计数法
    float f2 = 3e2; // 3 * 10^2 = 300
    cout << f2 << endl;
    float f3 = 3e-2; // 3 * 0.1^2 = 0.03
    cout << f3 << endl;
    system("pause");
    return 0;
}
7.4 字符型

作用:字符型变量用于显示单个字符
语法:char ch = 'a';

Tip:
(1) 在显示字符型变量,用单引号,不能用双引号
(2) 单引号内只能有一个字符,不能是字符串

C/C++字符型变量只占1个字节
字符型变量并不是把字符本身放到内存中存储,而是将对应的ASCIl编码放入到存储单元

#include <iostream>
using namespace std;

int main()
{
    // 字符型变量创建
    char ch = 'A';
    cout << ch << endl;
    // 字符型变量所占内存
    cout << sizeof(char) << endl;
    // 字符型变量常见错误
    /* char ch2 = "s";
     * char ch2 = 'ads';
     */
    // 字符型变量对应的ASCII编码 a-97 A-65
    cout << (int)ch << endl;
    system("pause");
    return 0;
}

在这里插入图片描述

7.5 转义字符

作用:用于表示一些不能显示出来的ASCII字符
现阶段常用的转义字符:\n \\ \t

#include <iostream>
using namespace std;

int main()
{
    // 换行符
    cout << "hello world" << '\n';
    // 反斜杠
    cout << "\\" << endl;
    // 水平制表符 整齐输出数据
    cout << "aaa\twad" << endl; // aaa(5个空格)wad 8个
    cout << "aaaaa\twad" << endl;
    cout << "aaaa\twad" << endl;
    system("pause");
    return 0;
}
7.6 字符串型

作用:用于表示一串字符
两种风格:

  1. C风格字符串:char 变量名[] = "字符串值";
  2. C++风格字符串:string 变量名 = "字符串值";

C++风格字符串,需要包含头文件 <string>

#include <iostream>
#include <string>
using namespace std;

int main()
{
    cout << "hello world" << endl;
    // char 字符串名[]
    // =后面用双引号包含起来字符串
    // C风格字符串
    char str1[] = "hello world";
    cout << str1 << endl;
    // C++风格字符串,需要包含头文件<string>
    string str2 = "hello world";
    cout << str2 << endl;
    system("pause");
    return 0;
}
7.7 布尔类型 bool

作用:布尔类型代表真或假的值
bool类型只有两个值:

  • true (本质是1)
  • false (本质是0)

bool类型占1个字节大小

#include <iostream>
using namespace std;

int main()
{
    // 创建bool类型
    bool flag = true;
    cout << flag << endl; // 1
    flag = false;
    cout << flag << endl; // 0
    // 查看bool类型所占内存空间
    cout << sizeof(bool) << endl; // 1
    system("pause");
    return 0;
}
7.8 数据的输入

作用:用于从键盘获取数据
关键字:cin
语法:cin >> 变量

#include <iostream>
#include <string>
using namespace std;

int main()
{
    int a = 0;
    // 整型
    cout << "Please input a: " << endl;
    cin >> a;
    cout << "a = " << a << endl;
    // 浮点型
    float f = 3.14f;
    cout << "please input f: " << endl;
    cin >> f;
    cout << "f = " << f << endl;
    // 字符型
    char ch = 'a';
    cout << "Please input ch: " << endl;
    cin >> ch;
    cout << "ch = " << ch << endl;
    // 字符串型
    string str = "hello";
    cout << "Please input str: " << endl;
    cin >> str;
    cout << "str = " << str << endl;
    // 布尔类型
    bool flag = false;
    cout << "Please input flag: " << flag << endl;
    cin >> flag; // 布尔类型只要非0都代表真
    cout << "flag = " << flag << endl;
    system("pause");
    return 0;
}
7.9 typedef

创建数据类型的别名:
(1)为名称复杂的类型创建别名,方便书写和记忆
(2)创建与平台无关的数据类型,提高程序兼容性
typedef 原数据类型名 别名;
C++11还可以用using关键字创建数据类型的别名
using 别名=原数据类型名;

#include <iostream>
using namespace std;

int main()
{
    typedef short int16_t;
    typedef int int32_t;
    typedef long long int64_t;
}

8 运算符

作用:用于执行代码的运算
在这里插入图片描述

8.1 算术运算符

在这里插入图片描述
两个小数是不可以做取模运算的
两个小数可以相除

8.2 赋值运算符

在这里插入图片描述

#include <iostream>
using namespace std;

int main()
{
    // =
    int a = 10;
    a = 100;
    cout << a << endl;
    // +=
    a = 10;
    a += 2;
    cout << a << endl;
    // -=
    a = 10;
    a -= 2;
    cout << a << endl;
    // *=
    a = 10;
    a *= 2;
    cout << a << endl;
    // /=
    a = 10;
    a /= 2;
    cout << a << endl;
    // %=
    a = 10;
    a %= 2;
    cout << a << endl;
    system("pause");
    return 0;
}
8.3 比较运算符

在这里插入图片描述

#include <iostream>
using namespace std;

int main()
{
    // ==
    int a = 10;
    int b = 20;
    cout << (a == b) << endl;
    // !=
    cout << (a != b) << endl;
    // >
    cout << (a > b) << endl;
    // <
    cout << (a < b) << endl;
    // >=
    cout << (a >= b) << endl;
    // <=
    cout << (a <= b) << endl;
    system("pause");
    return 0;
}
8.4 逻辑运算符

在这里插入图片描述
! && ||

#include <iostream>
using namespace std;

int main()
{
    // 非!
    // 在C++中, 除了0 都为真
    int a = 10;
    cout << !a << endl; // 0
    cout << !!a << endl;// 1
    // 与&&
    // &&: 两个条件都为真,结果才为真
    int b = 10;
    int c = 10;
    int d = 0;
    int e = 0;
    cout << (b && c) << endl;// 1
    cout << (b && d) << endl;// 0
    cout << (d && e) << endl;// 0
    // 或||
    // ||: 有一个真就是真,两个假就是假
    cout << (b || c) << endl; // 1
    cout << (b || d) << endl; // 1
    cout << (d || e) << endl; // 0
    system("pause");
    return 0;
}

9 程序流程结构

在这里插入图片描述

9.1 选择结构
9.1.1 if 语句

作用:执行满足条件的语句
在这里插入图片描述

#include <iostream>
using namespace std;

int main()
{
    // 单行if
    int score = 0;
    cout << "Please input score: " << endl;
    cin >> score;
    cout << "score = " << score << endl;
    if (score >= 650) // if后面不要加;
    {
        cout << "OK!!!!" << endl;
    }
    // 多行if
    if (score >= 650)
    {
        cout << "ok !!!!" << endl;
    }
    else
    {
        cout << "No !!!!" << endl;
    }
    // 多条件if
    if (score >= 650)
    {
        cout << "ok" << endl;
    }
    else if (score <= 250)
    {
        cout << "yes" << endl;
    }
    else
    {
        cout << "No" << endl;
    }
    // 嵌套if
    if (score >= 650)
    {
        if (score >= 700)
        {
            cout << "Beida" << endl;
        }
    }
    system("pause");
    return 0;
}

案例:三只小猪称体重
有三只小猪ABC,请分别输入三只小猪的体重,并且判断哪只小猪最重

#include <iostream>
using namespace std;

int main()
{
    int A, B, C;
    cin >> A >> B >> C;
    if (A > B)
    {
        if (A > C)
        {
            cout << "A最重" << endl;
        }
        else
        {
            cout << "C最重" << endl;
        }
    }
    else
    {
        if (B > C)
        {
            cout << "B最重" << endl;
        }
        else
        {
            cout << "C最重" << endl;
        }
    }
    system("pause");
    return 0;
}
9.1.2 三目运算符

语法:表达式1 ?表达式2 :表达式3

#include <iostream>
using namespace std;

int main()
{
    int a = 10;
    int b = 20;
    int c = 0;

    c = (a > b ? a : b);
    cout << c << endl;
    // 在C++中三目运算符返回的是变量,可以继续赋值
    (a < b ? a : b) = 100;
    cout << a << ' ' << b << endl;
    system("pause");
    return 0;
}
9.1.3 switch语句

在这里插入图片描述

#include <iostream>
using namespace std;

int main()
{
    // switch语句
    int score = 0;
    cin >> score;
    cout << score << endl;
    switch (score)
    {
        case 10:
            cout << "Classical" << endl;
            break;// 退出当前分支
        case 9:
            cout << "Classical" << endl;
            break;
        case 8:
            cout << "Very Good" << endl;
            break;
        default:
            cout << "common" << endl;
            break;
    }
    system("pause");
    return 0;
}

if 和 switch 区别
switch缺点:判断只能是整型或者字符型,不可以是一个区间
switch优点:结构清晰,执行效率高

9.2 循环结构
9.2.1 while
#include <iostream>
using namespace std;

int main()
{
    // while
    int num = 0;
    while (num < 10)// 0 ~ 9 写循环避免死循环
    {
        cout << num << endl;
        num++;
    }
    system("pause");
    return 0;
}

案例:猜数字
在这里插入图片描述
在这里插入图片描述

#include <iostream>
// time系统时间头文件包含
#include <ctime>
using namespace std;

int main()
{
    // 添加随机数种子 利用当前系统生成随机数,防止每次随机数都一样
    srand((unsigned int)time(NULL));
    // 系统生成随机数
    int num = rand()%100 + 1;// 0 ~ 99 -> 1 ~100
    // 玩家进行猜测
    int val = 0;
    while (1)
    {
        cin >> val;
        // 判断玩家的猜测 猜对,退出 猜错,提示猜的结果(过大,过小)

        if (val > num)
        {
            cout << "caice guoda" << endl;
        }
        else if (val < num)
        {
            cout << "guoxiao" << endl;
        }
        else
        {
            cout << "right" << endl;
            break;
        }
    }
    system("pause");
    return 0;
}
9.2.2 do…while
#include <iostream>
using namespace std;

int main()
{
    int num = 0;
    do {
        cout << num << endl;
        num++;
    }while (num < 10);
    system("pause");
    return 0;
}

do…while和while循环区别在于do…while会先执行一次循环语句
案例:水仙花数
在这里插入图片描述
在这里插入图片描述

#include <iostream>
using namespace std;

int main()
{
    // 100 ~ 999
    int num = 100;
    do {
        int a = 0;
        int b = 0;
        int c = 0;
        a = num % 10;     // 个位
        b = num / 10 % 10;// 十位
        c = num / 100;    // 百位
        if (a * a * a + b * b * b + c * c * c == num) // 如果是水仙花,才打印
        {
            cout << num << endl;
        }
        num++;
    }while (num < 1000);
    system("pause");
    return 0;
}
9.2.3 for循环语句
#include <iostream>
using namespace std;

int main()
{
//    for (int i = 0; i < 10; i++)
//    {
//        cout << i << endl;
//    }
    int i = 0;
    for ( ; ; )
    {
        if (i >= 10)
        {
            break;
        }
        i++;
        cout << i << endl;
    }
    system("pause");
    return 0;
}

在这里插入图片描述

#include <iostream>
using namespace std;

int main()
{
    for (int i = 1; i <= 100; i++)
    {
        if (i % 7 == 0 || i % 10 == 7 || i / 10 == 7)
        {
            cout << "lalala" << endl;
        }
        else
        {
            cout << i << endl;
        }
    }
    system("pause");
    return 0;
}
9.2.4 嵌套循环
#include <iostream>
using namespace std;

int main()
{
    for (int i = 0; i < 10; i++)// 外层循环
    {
        for (int j = 0; j < 10; j++)// 内层循环
        {
            cout << "* ";
        }
        cout << endl;
    }
    system("pause");
    return 0;
}

案例:乘法口诀表

#include <iostream>
using namespace std;

int main()
{
    for (int i = 1; i <=9; i++)
    {
        for (int j = 1; j <= i; j++)
        {
            cout << j << " * " << i << " = " << j * i << "   ";
        }
        cout << endl;
    }
    system("pause");
    return 0;
}
9.3 break语句

作用:用于跳出选择结构或者循环结构
使用:

  • switch条件语句中,终止case并跳出switch
  • 出现在循环语句中,作用是跳出当前的循环语句
  • 出现在嵌套循环中,跳出最近的内层循环语句
#include <iostream>
using namespace std;

int main()
{
    // switch
    int select = 0;
    cin >> select;
    switch (select)
    {
        case 1:
            cout << "common" << endl;
            break;
        case 2:
            cout << "middle" << endl;
            break;
        case 3:
            cout << "hard" << endl;
            break;
        default:
            break;
    }
    // 循环语句
    for (int i = 0; i < 10; i++)
    {
        if (i == 5)
        {
            break;
        }
        cout << i << endl;
    }
    // 嵌套循环语句
    for (int i = 0; i < 10; i++)
    {
        for (int j = 0; j < 10; j++)
        {
            if (j == 5)
            {
                break; // 退出内层循环
            }
            cout << " * ";
        }
        cout << endl;
    }
    system("pause");
    return 0;
}
9.4 continue语句

作用:在循环语句中,跳过本次循环中余下尚未执行的语句,继续执行下一次循环

#include <iostream>
using namespace std;

int main()
{
    // continue
    for (int i = 0; i <= 100; i++)
    {
        if (i % 2 == 0)
        {
            continue; // 可以筛选条件,执行到此不再往下执行,执行下一次循环
        }
        cout << i << endl;
    }
    system("pause");
    return 0;
}
9.5 goto语句

作用:无条件跳转语句
语法:goto 标记
在这里插入图片描述

#include <iostream>
using namespace std;

int main()
{
    // goto语句
    cout << "1" << endl;
    cout << "2" << endl;
    goto FLAG;
    cout << "3" << endl;
    cout << "4" << endl;
    FLAG:
    cout << "5" << endl;
    system("pause");
    return 0;
}

10 数组

10.1 一维数组定义方式

特点:
(1)数组中每个数据元素都是相同的数据类型
(2)数组是由连续的内存位置组成的

#include <iostream>
using namespace std;

int main()
{
    // 数组定义
    int arr1[5];
    arr1[0] = 1;
    arr1[1] = 2;
    int arr2[5] = {10, 20, 30, 40, 50};
    for (int i = 0; i < 5; i++)
    {
        cout << arr2[i] << endl;
    }
    int arr3[] = {1, 2, 3, 4, 5}; // 定义数组的时候,必须有初始长度
    system("pause");
    return 0;
}

Tip:
(1) 数组名的命名规范与变量名命名规范一致,不要和变量重名
(2) 数组中下标是从0开始索引

10.2 一维数组 - 数组名

一维数组名称的用途:
1、可以统计整个数组在内存中的长度 sizeof(arr)
2、可以获取数组在内存中的首地址 cout << arr << endl;

#include <iostream>
using namespace std;

int main()
{
    // 可以统计整个数组在内存中的长度
    int arr[10] = {1, 2, 4,5, 6,7, 8, 9, 10, 11};
    cout << sizeof(arr) << endl; // 40 = 4 * 10
    cout << sizeof(arr[0]) << endl; // 4
    cout << sizeof(arr) / sizeof(arr[0]) << endl; // 10
    // 可以获取数组在内存中的首地址
    cout << arr << endl;
    cout << &arr[0] << endl;

    system("pause");
    return 0;
}

数组名是一个常量,不可以进行赋值操作
在这里插入图片描述

五只小猪称体重

#include <iostream>
using namespace std;

int main()
{
    // 五只小猪称体重
    int arr[5] = {300, 350, 200, 400, 250};
    int max = 0;
    for (int i = 0; i < 5; i++)
    {
        if(arr[i] > max) max = arr[i];
    }
    cout << max << endl;
    system("pause");
    return 0;
}

数组元素逆置

#include <iostream>
using namespace std;

int main()
{
    int arr[5] = {1, 3, 2, 5, 4};
    for (int i = 0; i < 5; i++)
    {
        cout << arr[i] << ' ';
    }
    cout << endl;
    int start = 0;
    int end = sizeof(arr) / sizeof(arr[0]) - 1;
    while (start < end)
    {
        int temp = arr[start];
        arr[start] = arr[end];
        arr[end] = temp;
        start++;
        end--;
    }
    for (int i = 0; i < 5; i++)
    {
        cout << arr[i] << ' ';
    }
    cout << endl;
    system("pause");
    return 0;
}

冒泡排序
在这里插入图片描述

#include <iostream>
using namespace std;

int main()
{
    int arr[9] = {4, 2, 8, 0, 5, 7, 1, 3, 9};
    for (int i = 0; i < 9; i++)
    {
        cout << arr[i] << ' ';
    }
    cout << endl;
    for (int i = 0; i < 9 - 1; i++)
    {
        for (int j = 0; j < 9 - i - 1; j++)
        {
            if (arr[j] > arr[j + 1])
            {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
    for (int i = 0; i < 9; i++)
    {
        cout << arr[i] << ' ';
    }
    cout << endl;
    system("pause");
    return 0;
}
10.3 二维数组定义方式

在这里插入图片描述

#include <iostream>
using namespace std;

int main()
{
    // 二维数组定义方式
    // No.1
    int arr1[2][3];
    arr1[0][0] = 1;
    arr1[0][1] = 2;
    arr1[0][2] = 3;
    arr1[1][0] = 4;
    arr1[1][1] = 5;
    arr1[1][2] = 6;
    // No.2
    int arr2[2][3] =
            {
                    {1, 2, 3},
                    {4, 5, 6}
            };
    // No.3
    int arr3[2][3] = {1, 2, 3, 4, 5, 6};
    // No.4
    int arr4[][3] = {1,2,3,4,5,6,7,8,9};
    for (int i = 0; i < 2; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            cout << arr1[i][j] << ' ';
        }
    }
    system("pause");
    return 0;
}
10.4 二维数组名

(1)查看二维数组所占内存空间
(2)获取二维数组首地址

#include <iostream>
using namespace std;

int main()
{
    double arr[2][3] =
            {
                    {1, 2, 3},
                    {4, 5, 6}
            };
    cout << sizeof(arr) << endl;
    cout << sizeof(arr[0]) << endl; // 第一行占用内存
    cout << sizeof(arr[0][0]) << endl; // 第一个元素占用内存
    cout << sizeof(arr) / sizeof(arr[0]) << endl;
    cout << sizeof(arr[0]) / sizeof(arr[0][0]) << endl;
    cout << arr << endl;
    cout << arr[0] << endl;
    cout << &arr[0][0] << endl;
    system("pause");
    return 0;
}

案例:
在这里插入图片描述

#include <iostream>
using namespace std;

int main()
{
    /*
     * 0 300
     * 1 240
     * 2 210
     * */
    int score[3][3] =
    {
            {100, 100, 100},
            {90, 50, 100},
            {60, 70, 80}
    };
    for (int i = 0; i < 3; i++)
    {
        int sum = 0;
        for (int j = 0; j < 3; j++)
        {
            sum += score[i][j];
        }
        cout << i << ' ' << sum << endl;
    }
    system("pause");
    return 0;
}

11 函数

函数的声明和定义可以书写在一起,也可以分开,如果书写在一起,一般放在main函数的上面,如果分开,一般在main函数的上面声明,在main函数的下面定义

C++中定义变量的场景主要有五种:
1)在全部函数外面定义的是全局变量。
2)在头文件中定义的是全局变量。
3)在函数和语句块内部定义的是局部变量。
4)函数的参数是该函数的局部变量。
5)函数内部用static修饰的是静态局部变量。

当程序想要使用全局变量的时候应该先考虑使用static(考虑到数据安全性)

11.1 函数分文件编写

*.h:声名全局变量,函数声名,数据结构和类的声名
*.cpp:函数的定义、类的定义

11.2 在VS中调试程序

在这里插入图片描述

11.3 递归函数

递归函数:运行时调用自己的函数
Tip:递归函数中一定要有递归终止的条件,否则就是死递归
在这里插入图片描述

#include <iostream>
using namespace std;

int f(int x)
{
    if (x == 0) return 0; // 递归截止条件
    return x + f(x - 1);
}
int main()
{
    cout << "f(3)= " << f(3) << endl;
    system("pause");
    return 0;
}

12 指针

在这里插入图片描述
C++用运算符&获取变量在内存中的起始地址
指针变量简称指针,它是一种特殊的变量,专用于存放变量在内存中的起始地址

不管是整型、浮点型、字符型,还是其它的数据类型的变量,它的地址都是一个十六进制数。我们用整型指针存放整数型变量的地址;用字符型指针存放字符型变量的地址;用浮点型指针存放浮点型变量的地址,用自定义数据类型指针存放自定义数据类型变量的地址。

指针=&变量名
Tip:
(1) 对指针的赋值操作被称为“指向某变量”,被指向的变量数据类型称为“基类型”
(2) 指针的数据类型与基类型不符,编译会出现警告。但是,可以强制转换它们的类型

12.1 使用指针

指针用于函数的参数
值传递:函数的形参是普通变量
传地址:可以在函数中修改实参的值;减少内存拷贝,提升性能

12.2 用const修饰指针

(1)常量指针
语法:const 数据类型 *变量名

不能通过解引用的方法修改内存地址中的值(用原始的变量名是可以修改的)

1.一般用于修饰函数的形参,表示不希望在函数里修改内存地址中的值
2.如果用于形参,虽然指向的对象可以改变,但这么做没有任何意义
3.如果形参的值不需要改变,建议加上const修饰,程序可读性更好
(2)指针常量
语法:数据类型 *const 变量名

指向的变量(对象)不可改变

1.定义的同时必须初始化
2.可以通过解引用的方法修改内存地址中的值
3.C++把指针常量做了一些特别的处理,叫引用
(3)常指针常量
语法:const 数据类型 *const 变量名;

指向的变量(对象)不可改变,不能通过解引用的方法修改内存地址中的值

13 void 关键字

用途:
(1)函数返回值用void
(2)函数的参数填void,表示函数不需要参数
(3)形参用void*, 表示接受任意数据类型的指针
Tip:
1.不能用void声名变量,它不能代表一个真实的变量,但是void* 可以
2.不能对void* 指针直接解引用(需要转换成其他类型的指针)
3.把其他类型的指针赋值给void*指针不需要转换,反之要转换

#include <iostream>
using namespace std;
void func(string name, void* p)
{
    cout << name << " " << p << endl;
    cout << name << " " << *(char*)p << endl;
}
int main()
{
    int a = 80;
    char b = 'X';
    cout << &a << endl;
    cout << &b << endl;
    
    func("a", &a);
    func("b", &b);
    return 0;
}

13 C++内存模型

内存主要分成四个区:栈、堆、数据段、代码段
在这里插入图片描述
栈和堆的主要区别:
(1)管理方式不同:栈是系统自动管理的,出作用域会被自动释放;堆需要手动释放,若程序中不释放,程序结束由操作系统回收
(2)空间大小不同:堆内存大小受限于物理内存空间;而栈小的可怜,一般只有8M(可以修改系统参数)
(3)分配方式不同
(4)分配效率不同
(5)是否产生碎片
(6)增长方向不同

14 动态分配内存new和delete

栈区的效率很高,但是空间很小;如果需要处理大量的数据,就必须使用堆区的内存

#include <iostream>
using namespace std;

int main()
{
    // 1 声名一个指针
    int *p;
    // 2 用new运算符向系统申请一块内存,让指针指向这块内存
    p = new int(5);
    // int *p = new int(5);
    // 3 通过对指针解引用的方法,像使用变量一样使用这块内存
    cout << "*p = " << *p << endl;
    *p = 8;
    cout << "*p = " << *p << endl;
    // 4 如果这块内存不用了,用delete运算符释放它
    delete p;
}

Tip:
(1)动态分配出来的内存没有变量名,只能通过操作指针来操作内存中的数据
(2)如果动态内存分配的内存不用了,必须用delete释放它,否则有可能用尽系统的内存
(3)动态分配的内存生命周期与程序相同,程序退出时,如果没有释放,系统自动回收
(4)就算指针的作用域失效,指向的内存也不会释放
(5)用指针跟踪已分配的内存,不能跟丢

15 二级指针

指针:用于存放普通变量的地址
二级指针:存放指针变量的地址
语法:数据类型** 指针名;
1.传递地址
2.存放动态分配的内存的地址

#include <iostream>
using namespace std;

int main()
{
    int a = 8;
    cout << "a = " << a << " " << &a << endl;
    int* p = &a;
    cout << "p = " << p << " " << &p << " " << *p << endl;
    int** h = &p;
    cout << "h = " << h << " " << &h << " " << *h << endl;
}

16 空指针

C/C++,用0或NULL都可以表示空指针。
声名指针后,在赋值之前,让他指向空,表示没有指向任何地址。
(1)后果:
1.对空指针解引用,程序会崩溃
2.如果对空指针使用delete运算符,系统忽略该操作,不会出现异常。所以,内存被释放后,也该把指针指向空
3.在函数中,应该判断形参是否为空指针的代码,目的是保证程序的健壮性
(2)C++11的nullptr
用0和NULL表示空指针会产生歧义,c++11建议用nullptr,(void*)0

注意:在Linux平台下,如果使用nullptr,编译需要加-std=c++11参数

#include <iostream>
using namespace std;

void func(int* no, string* str)
{
    if ((no == 0) || (str == 0)) return;
    cout << *no << " " << *str << endl;
}

int main()
{
    int* bh = 0;
    string* message = 0;
    func(bh, message);
    delete bh;
    delete message;
    return 0;
}

17 野指针

野指针:指针指向的不是一个有效合法的地址
访问野指针,可能会造成程序的崩溃
出现野指针的情况:
(1)指针未初始化
(2)指针指向了动态分配的内存,内存被释放后,指针不会置空,但是,指向的地址失效
(3)指针指向的变量已经超越变量的作用域,让指针指向了函数的局部变量,或者把函数的局部变量的地址作为返回值赋值给指针

#include <iostream>
using namespace std;

int* func()
{
    int a = 2;
    cout << a << ' ' << &a << endl;

    return &a;
}
int main()
{
//    int *p = new int(5);
//    cout << p << ' ' << *p << endl;
//    delete p;
//    cout << p << ' ' << *p << endl;
    int* p = func();
    cout << p << ' ' << *p << endl;

    return 0;
}

规避方法:
1.指针在定义的时候,如果没地方指,就初始化为nullptr
2.动态分配的内存被释放后,将其置为nullptr
3.函数不要返回局部变量的地址

野指针的危害比空指针大很多,访问野指针,可能会造成程序的崩溃。程序的表现是不稳定,增加了调试程序的难度

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/155940.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深度学习入门(第四天)——递归神经网络与词向量原理解读

一、RNN网络架构解读 常规神经网络并不能考虑时间序列的特征&#xff08;比如前天昨天今天或者带有前后关联的特征&#xff09;&#xff0c;现在每个特征都是独立考虑的&#xff0c;那么如果有这样的特征&#xff0c;网络应该怎么学呢 而递归递归网络hidden这里的转回箭头&…

全球地表水数据集JRC Global Surface Water Mapping Layers, v1.2数据

简介&#xff1a; 全球地表水覆盖&#xff08;Global Surface Water&#xff09;是利用1984至2019年获取的landsat5、landsat7和landsat8的卫星影像&#xff0c;生成分辨率为30米的一套全球地表水覆盖的地图集。用户可以在全球尺度上按地区回溯某个时间上地表水分的变化情况。…

MySQL内部组件与日志详解

MySQL的内部组件结构 MySQL 可以分为 Server 层和存储引擎层两部分。 Server 层主要包括连接器、查询缓存、分析器、优化器、执行器等&#xff0c;涵盖 MySQL 的大多数核心服务功能&#xff0c;以及所有的内置函数&#xff08;如日期、时间、数学和加密函数等&#xff09;&am…

Android开发APP显示头部Bar

Android开发显示头部Bar 需求&#xff1a; 显示如下图&#xff1a; 显示头部Bar&#xff0c;颜色也能自定义。 解决方案 这个修改是在如下三个文件里进行修改&#xff1a; 按顺序修改&#xff1a; themes.xml(night): <resources xmlns:tools"http://schemas.andr…

21 - 深入JVM即时编译器JIT,优化Java编译

说到编译&#xff0c;我猜你一定会想到 .java 文件被编译成 .class 文件的过程&#xff0c;这个编译我们一般称为前端编译。Java 的编译和运行过程非常复杂&#xff0c;除了前端编译&#xff0c;还有运行时编译。由于机器无法直接运行 Java 生成的字节码&#xff0c;所以在运行…

Odoo 15开发手册第六章 模型 - 结构化应用数据

本章我们更进一步学习模型层&#xff0c;以及如何使用模型来设计支撑应用的数据结构。我们会探讨可用的模型类型&#xff0c;以及在使用这些类型时如何定义强制进行数据验证的约束。 模型由支持不同数据类型的数据字段组成&#xff0c;一些字段类型支持定义模型间的关联。对于…

excel导入 Easy Excel

依旧是框架感觉有东西&#xff0c;但是确实是模拟不出来&#xff0c;各种零零散散的件太多了 controller层 ApiOperation(value "导入Excel", notes "导入Excel", httpMethod "POST", response ExcelResponseDTO.class)ApiImplicitParams({…

回调方法Callbak方法的理解——Java中回调的实现方式 从系统调用角度理解回调

目录 回调方法实现用反射实现直接调用callback进化&#xff1a;接口实现分离 匿名内部类 到 函数式编程 从系统调用角度理解回调同步调用异步调用不需要对方结果需要对方的结果 菜鸡问大佬问题案例同步回调异步回调基于Future的半同步 回调方法就是一个参数,将一个A方法作为参数…

Power Automate-创建自定义连接器

点击左侧导航栏&#xff0c;更多&#xff0c;点击全部发现 点击下方的自定义连接器 点击从空白创建 注意命名要用英文 常规信息中可以上传连接器icon、写一些说明 方案是观察接口地址前面的文本&#xff0c;主机是下方接口地址中蓝色框中的内容 点击下一步&#xff0c;根据API自…

CTF-PWN-堆-【前置知识】

CTF-PWN-堆 堆申请堆块main_areanabrk&sbrk函数mallocfreefree后top chunk 堆 由malloc alloc realloc 函数分配 chunk的前指的是地址低的&#xff0c;chunk的高指的是地址高的 申请堆块 ptmalloc2堆管理器&#xff1a; 通俗的讲就是相当于一个”中间商”&#xff0c;在…

Python编程技巧 – 使用列表(list)

Python编程技巧 – 使用列表(list) Python Programming Skills – Using a List 在Python编程语言中&#xff0c;我们会用到许多列表&#xff08;List&#xff09;。 一门强大的编程语言会包含列表&#xff08;或者数组&#xff09;的数据结构。列表&#xff08;或数组&#…

cpolar+LightPicture,将个人电脑改造成公网图床服务器

文章目录 1.前言2. Lightpicture网站搭建2.1. Lightpicture下载和安装2.2. Lightpicture网页测试2.3.cpolar的安装和注册 3.本地网页发布3.1.Cpolar云端设置3.2.Cpolar本地设置 4.公网访问测试5.结语 1.前言 现在的手机越来越先进&#xff0c;功能也越来越多&#xff0c;而手机…

C++ Qt 学习(九):模型视图代理

1. Qt 模型视图代理 Qt 模型视图代理&#xff0c;也可以称为 MVD 模式 模型(model)、视图(view)、代理(delegate)主要用来显示编辑数据 1.1 模型 模型 (Model) 是视图与原始数据之间的接口 原始数据可以是&#xff1a;数据库的一个数据表、内存中的一个 StringList&#xff…

什么是持续集成的自动化测试?

持续集成的自动化测试 如今互联网软件的开发、测试和发布&#xff0c;已经形成了一套非常标准的流程&#xff0c;最重要的组成部分就是持续集成&#xff08;Continuous integration&#xff0c;简称CI&#xff0c;目前主要的持续集成系统是Jenkins&#xff09;。 那么什么是持…

Python爬虫教程:从入门到实战

更多Python学习内容&#xff1a;ipengtao.com 大家好&#xff0c;我是涛哥&#xff0c;今天为大家分享 Python爬虫教程&#xff1a;从入门到实战&#xff0c;文章3800字&#xff0c;阅读大约15分钟&#xff0c;大家enjoy~~ 网络上的信息浩如烟海&#xff0c;而爬虫&#xff08;…

4G工业路由器智慧电梯联网应用方案

随着电梯老旧增多及日常管理上缺失&#xff0c;电梯安全运行上存在一定的问题&#xff0c;从全国电梯统计数据中可以发现&#xff0c;主要的电梯困人、故障事件发生在住宅小区&#xff0c;当前&#xff0c;住宅小区的电梯绝大多数是通过物业公司负责管理&#xff0c;物业公司安…

【尘缘赠书活动第四期】推荐几本架构师成长和软件架构技术相关的好书,助你度过这个不太景气的寒冬!

目录 1 《高并发架构实战&#xff1a;从需求分析到系统设计》2《架构师的自我修炼&#xff1a;技术、架构和未来》3《中台架构与实现&#xff1a;基于DDD和微服务》4《分布式系统架构&#xff1a;架构策略与难题求解》5《流程自动化实战&#xff1a;系统架构和软件开发视角 》6…

验证码识别之OCR识别

验证码识别&#xff1a; 背景&#xff1a; ​ 决定开一个专题给大家讲一下验证码识别&#xff0c;不要多想&#xff0c;我们不搞深度学习&#xff0c;知识用于攻破模拟登录的时候弹出的验证码&#xff0c;后续会给大家讲讲滑块等等&#xff0c;反爬虫策略如何应对。 好了&am…

大会技术“硬核”资讯来啦!点击预约 IoTDB 现场一对一调优咨询服务

承诺大家的&#xff0c;2023 IoTDB 用户大会现场“快讯”第一弹来啦&#xff01; 我们将在大会现场设置 IoTDB Workshop&#xff0c;IoTDB 原厂团队将免费提供一对一技术咨询、使用调优、疑问解答等服务。 现场提供的一对一咨询、调优时长为 30 分钟&#xff0c;在您预约的时间…

Linux_VMware 软件安装与虚拟机

从这里开始&#xff0c;我们就踏上了学习 Linux 的路程。长路漫漫亦灿灿&#xff0c;祝我也祝所有看到这篇文章的朋友&#xff01;&#xff01;&#xff01; 参考书目&#xff1a;【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.81 / ARM 裸机与嵌入式 Linux 驱动…