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

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

1 第一个C程序-HelloWorld

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

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

2 程序的注释

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

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

3 变量

变量存在的意义:方便我们管理内存空间
作用:给一段指定的内存空间起名,方便操作这段内存
语法:数据类型 变量名 = 初始值;
C++基础从0到1入门编程(一)_第1张图片

#include 
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 
using namespace std;
#define Day 7

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

5 C++常用编程关键字

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

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

C++基础从0到1入门编程(一)_第2张图片

#include 
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++规定在创建一个变量或者常量时,必须指定相应的数据类型,否则无法给变量分配内存。
数据类型存在意义:给变量分配合适的内存空间
C++基础从0到1入门编程(一)_第3张图片

#include 
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 
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 
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
区别:表示的有效数字范围不同
C++基础从0到1入门编程(一)_第4张图片

#include 
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 
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 
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++风格字符串,需要包含头文件

#include 
#include 
using namespace std;

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

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

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

bool类型占1个字节大小

#include 
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 
#include 
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 
using namespace std;

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

8 运算符

作用:用于执行代码的运算
C++基础从0到1入门编程(一)_第5张图片

8.1 算术运算符

C++基础从0到1入门编程(一)_第6张图片
两个小数是不可以做取模运算的
两个小数可以相除

8.2 赋值运算符

C++基础从0到1入门编程(一)_第7张图片

#include 
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 比较运算符

C++基础从0到1入门编程(一)_第8张图片

#include 
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 逻辑运算符

C++基础从0到1入门编程(一)_第9张图片
! && ||

#include 
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 程序流程结构

C++基础从0到1入门编程(一)_第10张图片

9.1 选择结构
9.1.1 if 语句

作用:执行满足条件的语句
C++基础从0到1入门编程(一)_第11张图片

#include 
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 
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 
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语句

C++基础从0到1入门编程(一)_第12张图片

#include 
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 
using namespace std;

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

案例:猜数字
在这里插入图片描述
C++基础从0到1入门编程(一)_第13张图片

#include 
// time系统时间头文件包含
#include 
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 
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会先执行一次循环语句
案例:水仙花数
在这里插入图片描述
C++基础从0到1入门编程(一)_第14张图片

#include 
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 
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 
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 
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 
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 
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 
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 标记
C++基础从0到1入门编程(一)_第15张图片

#include 
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 
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 
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;
}

数组名是一个常量,不可以进行赋值操作
C++基础从0到1入门编程(一)_第16张图片

五只小猪称体重

#include 
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 
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;
}

冒泡排序
C++基础从0到1入门编程(一)_第17张图片

#include 
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 二维数组定义方式

C++基础从0到1入门编程(一)_第18张图片

#include 
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 
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;
}

案例:
C++基础从0到1入门编程(一)_第19张图片

#include 
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中调试程序

C++基础从0到1入门编程(一)_第20张图片

11.3 递归函数

递归函数:运行时调用自己的函数
Tip:递归函数中一定要有递归终止的条件,否则就是死递归
C++基础从0到1入门编程(一)_第21张图片

#include 
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++基础从0到1入门编程(一)_第22张图片
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 
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++内存模型

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

14 动态分配内存new和delete

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

#include 
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 
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 
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 
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.函数不要返回局部变量的地址

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

你可能感兴趣的:(C++,c++,学习,linux)