C++ programming from 0 to 1

1. Variables

1 byte 2 bytes 4 bytes 8 bytes
char short

int

long (linux64 bit)
float long long
long(win/linux32位) double

switch (only integer or character) {}

Generate random numbers 0~99: rand()%100;

//随机数种子生成随机数每次不同:
#include <ctime>
srand((unsigned int)time(NULL));
  • Narcissus number: the sum of each 3-digit power of a 3-digit number is equal to itself

  • jump statement

    • break: terminate the entire loop

    • continue: Skip the next statement to execute the next loop

    • goto (after pure uppercase): unconditional jump

2. Array

2.1. One-dimensional array

Subscript at the end of the array: sizeof(arr)/sizeof(arr[0]-1)

//冒泡
int arr[9] = {5,8,2,3,4,1,6,2,7};
    
    //总共排列的轮数
    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;

2.2. Two-dimensional array

There are 4 ways to define a two-dimensional array:

1. Data type array name [ number of rows ] [ number of columns ];

2. (recommended) data type array name [ row number ] [ column number ] =

{

        //Intuitively, there are 2 rows and 2 columns

        { data1,data2 },

        { Data 3, Data 4 }

};

3. Data type array name [ number of rows ] [ number of columns ] = { data 1, data 2, data 3, data 4 };//Automatically divide the number of rows according to the number of columns

4. Data type array name [ ][ number of columns ] = { data 1, data 2, data 3, data 4 };//The number of rows is automatically divided according to the number of columns 

//计算二维数组的行数
sizeof(arr)/sizeof(arr[0])
//计算二维数组的列数
sizeof(arr[0])/sizeof(arr[0][0])

Visit the first address: arr

Access the first address of the first row: arr[0]

Access the first address of the second row: arr[1]

Access the first address of the first element: & arr[0][0] // must have an address symbol

//二维数组案例-考试成绩统计
#include <iostream>
using namespace std;
#include <string>

int main()
{
    //1、列出成绩    
    int scores[3][3] =
    {
        {100,100,100},
        {90,80,70},
        {60,50,40}
    };
    
    string names[3] = {"张三","李四","狗五"};
    
    //2、统计每人的总分
    //控制行数
    for(int i=0 ; i<3 ; i++)
    {
        int sum = 0;//统计分数总和变量
        //控制列数
        for(int j=0 ; j<3 ; j++)
        {
            sum += scores[i][j];
        }
        cout<<names[i]<<"的总分为:"<<sum<<endl;
    }
    
    return 0;
}

3. Function

3.1. The basic form of the function: no argument and no inversion, no argument and inversion, parameter and no inversion, and parameter and inversion

语法:
返回值类型 函数名 (参数列表)
{
    声明和语句;
    return x;
}
//若返回值类型为:void ,则最后写成 return;

3.2. The function declaration can be written multiple times, and the definition can only be written once.

3.3. Function file writing

//1、在“头文件”新建.h后缀名的头文件
//2、在“源文件”新建.cpp后缀名的源文件

//3、在头文件中写函数的声明
#include <iostream>
using namespace std;
//写函数声明

//4、在源文件中写函数的定义
#include "函数名.h"
//写函数定义

4. Pointer

4.1. Definition of pointer

int a = 10;

//定义指针:数据类型 * 指针变量名 或者 数据类型 * 指针变量名 = &地址变量名
int * p;

//引用:&放在一个变量声明或者是函数的形参声明前


//取地址:&放在一个已经定义的变量前
p = &a;

//两者打印结果一样
cout<<"a的地址为:"<<&a<<endl;
cout<<"指针p为:"<<p<<endl;

//指针前加 * 代表解引用,找到指针指向内存中的数据,即 a 的值
*p = 1000;

//两者打印结果一样
cout<<"a="<<a<<endl;
cout<<"*p="<<*p<<endl;

4.2. Null pointer (the pointer variable points to the space numbered 0 in the memory)

//用途:初始化指针变量
int * p = NULL;

//注意:空指针指向的内存是不可以访问的
//0~255之间的内存编号是系统占用的,不可访问
*p = 100;//运行报错

4.3. Wild pointer (pointer variable points to illegal memory space)

//在程序中,尽量避免出现野指针
int * p = (int *)0x1100;//未声明就访问
cout<<*p<<endl;//报错 

Null pointers and wild pointers are not the space we apply for, so don't access

4.4. const modifies pointers or constants (principle: whoever const is before is immutable)

int a=10;
int b=10;

//1、const 修饰指针:常量指针(把const读成常量,把*读成指针)
const int * p = &a;

//指针指向的值不可以改,指针的指向可以改
*p = 20;//报错
p = &b;//正确

//2、const 修饰常量:指针常量
int * const p2 = &a;
*p2 = 100;//正确
p2 = &b;//报错

//3、const 修饰指针和常量
const int * const p3 = &a;
*p3 = 100;//报错
p3 = &b;//报错

4.5. Pointer access to array

int arr[3] = {1,2,3};

int * p = arr;//指向数组的指针,arr就是数组首地址

cout<<"指针访问第一个元素:"<<*p<<endl;

//利用指针遍历数组
for(int i=0 ; i<3 ; i++)
{
    cout<<*p<<endl;
    p++;//让指针向后偏移4个字节
}

4.6. Address transfer (value transfer does not change the actual parameter, address transfer changes the actual parameter)

void swap(int * p1,int * p2)
{
    //函数体
}

int main()
{
    int a = 10;
    int b = 20;
    swap(&a,&b);//地址传递会改变实参

    return 0;
}

4.7. Pointer array function realizes bubbling

//指针数组函数实现冒泡排序

//冒泡排序函数
void bubbleSort(int * arr, int len)
{
    for(int i=0 ; i<len-1 ; i++)
    {
        for(int j=0 ; j<len-i-1 ; j++)
        {
            if(arr[j]>arr[j+1])
            {
                int temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
            }
         }
    }
}

void printArray(int * arr , int len)
{
    for(int i=0 ; i<len ; i++)
    {
        cout<<arr[i]<<endl;
    }
    
}

int main()
{
   //1、创建数组
   int arr[10] = {3,2,9,8,3,9,5,7,4,5};
   
   //数组长度(关键:可灵活处理数组长度)
   int len = sizeof(arr)/sizeof(arr[0]);// 40/4=10
   
   //2、创建函数,实现冒泡排序
   bubbleSort(arr,len);
   
   //3、打印排序后的数组
   printArray(arr,len);
   
    return 0;
}

5. Structure

5.1. Concept: a user-defined data type that allows users to store different data types

/*
语法:(定义结构体时的关键字struct不可省)
struct 结构体名
{ 
	数据类型 变量名1;
	数据类型 变量名2;
};
*/

struct Student
{ 
	string name;
	int age;
};

//3种通过结构体创建变量的方式

//1、struct 结构体名 变量名
struct Student s1;//(创建结构体变量时的关键字struct可省)
//可直接写成:Student s1;

s1.name = "张三";//用操作符 . 访问成员
s1.age = 10;

//2、struct 结构体名 变量名 = { 成员1值 , 成员2值...}
struct Student s2 = {"李四",19};//(此struct可省略)

//3、定义结构体时顺便创建变量(不建议用)
struct Student
{ 
	string name;
	int age;
}s3;//尾括号加变量名就顺便创建结构体变量

s3.name = "张三";
s3.age = 10;

5.2, structure array

Function: put the custom structure into the array for easy maintenance

//语法:struct 结构体名 数组名[元素个数] = {
   
   {},{},{}}; 
struct Student
{
    string name;
    int age;
};

int main()
{
    struct Student arr[2] = 
    {
        {"张三",10},
        {"李四",20}    
    };

    //访问数组中的元素
    cout<<arr[0].name<<endl;
}

5.3. Structure pointer

Role: access members in the structure through pointers

struct Student
{ 
	string name;
	int age;
};

//1、创建学生结构体变量
struct Student s = {"小明",19};

//2、通过指针指向结构体变量
struct Student * p = &s;

//3、利用操作符 -> 访问结构体中的成员
cout<<p->name<<endl;

5.4. Structure nesting

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

struct Student 
{
    string name;
    int age;
};

struct Teacher
{
    string name;
    int id;
    struct Student stu;//结构体中再嵌套结构体
};


int main()
{
   //创建结构体
   struct Teacher t1;
   t1.name = "老师";
   t1.id = 10;
   t1.stu.name = "学生";//对结构体中的结构体赋值操作
   t1.stu.age = 18;
   
   cout<<t1.name<<endl;
   cout<<t1.id<<endl;
   cout<<t1.stu.name<<endl;
   cout<<t1.stu.age<<endl;
   
    return 0;
}

5.5. The structure is used as a function parameter (the value transfer does not change the data in the main function, but the address transfer will change)

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

struct Student 
{
    int age;
};

//代码检测时把函数printStudent1或者printStudent2注释其中之一
//值传递
void printStudent1(struct Student s)
{
    s.age = 19;
    cout<<"值传递值:"<<s.age<<endl;//值传递输出为19,主函数输出仍为18,不改主函数的值
}

void printStudent2(struct Student * p)
{
    p->age = 20;
    cout<<"地址传递值:"<<p->age<<endl;//地址传递输出为20,主函数输出也为20,改变主函数的值
}

int main()
{
   //创建结构体
   struct Student s;
   s.age = 18;
   printStudent1(s);
   //printStudent2(&s);
   cout<<"主函数值:"<<s.age<<endl;
   
    return 0;
}

5.6, the use of structure const

Function: use const to prevent misoperation

#include <iostream>
using namespace std;

struct Student 
{
    int age;
};


//将函数中的形参改为指针,可以减少内存空间,而且不会复制新的副本出来
void printStudent1(const struct Student *s)//形参改为指针
{
    //s->age = 19;//报错
    cout<<s->age<<endl;
    
}

int main()
{
   //创建结构体
   struct Student s;
   s.age = 18;
   printStudent1(&s);//加个取地址符
 
    return 0;
}

5.7. Structure case

/*
案例描述1 :学校正在做毕设项目,每名老师带领5个学生,总共有3名老师,需求如下。
设计学生和老师的结构体,其中在老师的结构体中,有老师姓名和一个存放5名学生的数组作为成员。
学生的成员有姓名、考试分数。
创建数组存放3名老师,通过函数给每个老师及所带的学生赋值。
最终打印出老师数据以及老师所带的学生数据。
*/

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

//1、创建老师和学生的结构体
//学生的结构体
struct Student 
{
    //学生姓名
    string sName;
    
    //学生分数
    int score;
};

//老师的结构体
struct Teacher
{
    //老师姓名
    string tName;
    
    //每名老师所带学生的数组
    struct Student sArray[5];
};

//tips:赋值函数和打印函数有许多相同的地方
//3、给老师和学生赋值的函数
void allocateSpace(struct Teacher tArray[],int len)
{
    string nameSeed = "ABCDE";
    
    //循环给老师赋值
    for(int i=0 ; i<len ; i++)
    {
        tArray[i].tName = "Teacher_";
        tArray[i].tName += nameSeed[i];
        
        //循环给每名老师所带的学生赋值
        for(int j=0 ; j<5 ; j++)
        {
            tArray[i].sArray[j].sName = "Student_";
            tArray[i].sArray[j].sName += nameSeed[j];
            
            int random = rand()% 61+40; //40~100
            tArray[i].sArray[j].score = random;
        }
        
    }
    
}

//4、打印所有老师及所带学生信息
void printInof(struct Teacher tArray[],int len)
{
    
    //循环打印老师的信息
    for(int i=0 ; i<len ; i++)
    {
        cout<<"老师姓名:"<<tArray[i].tName<<endl;
        
        //循环打印每名老师所带的学生信息
        for(int j=0 ; j<5 ; j++)
        {
            cout<<"\t学生姓名:"<<tArray[i].sArray[j].sName
                <<" 考试分数:"<<tArray[i].sArray[j].score
                <<endl;
        }
    }
}

int main()
{
   
   //随机数种子
   srand((unsigned int)time(NULL));
   
   //2、创建3名老师的数组
   struct Teacher tArray[3];
  
   //tips:赋值函数和打印函数有许多相同的地方
 
   //3、通过函数给3名老师的信息赋值,并给老师带的学生信息赋值
   int len = sizeof(tArray)/sizeof(tArray[0]);
   allocateSpace(tArray,len);
   
   //4、打印所有老师及所带学生信息
   printInof(tArray,len);
 
    return 0;
}
/*
案例描述2 :设计一个英雄的结构体,包括成员姓名,年龄,性别;
创建结构体数组,数组中存放5名英雄。
通过冒泡排序的算法,将数组中的英雄按照年龄进行升序排序,
最终打印排序后的结果。
*/

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

//1、设计英雄结构体
struct Hero 
{
    //姓名
    string name;
    
    //年龄
    int age;
    
    //性别
    string sex;
};

//冒泡排序:实现年龄升序排序
void bubbleSort(struct Hero heroArray[],int len)
{
    for(int i=0 ; i<len-1 ; i++)
    {
        for(int j=0 ; j<len-i-1 ; j++)
        {
            
            //此处是关键
            if(heroArray[j].age>heroArray[j+1].age)
            {
                struct Hero temp = heroArray[j];
                heroArray[j] = heroArray[j+1];
                heroArray[j+1] = temp;
            }
        }
    }
}

//打印排序后数组中的信息
void printHero(struct Hero heroArray[],int len)
{
    for(int i=0 ; i<len ; i++)
    {
        cout<<"姓名:"<<heroArray[i].name
            <<"年龄:"<<heroArray[i].age
            <<"性别:"<<heroArray[i].sex
            <<endl;
    }
}

int main()
{
   
   //2、创建数组存放5名英雄
   struct Hero heroArray[5] = 
   {
       {"刘备",23,"男"},
       {"关羽",22,"男"},
       {"张飞",20,"男"},
       {"赵云",21,"男"},
       {"貂蝉",19,"女"}
   };
   
   int len = sizeof(heroArray)/sizeof(heroArray[0]);
   
   cout<<"排序前的打印:"<<endl;
   
   //可作为测试代码
   for(int i=0 ; i<len ; i++)
   {
       cout<<"姓名:"<<heroArray[i].name
           <<"年龄:"<<heroArray[i].age
           <<"性别:"<<heroArray[i].sex
           <<endl;
   }
   
   
   //3、对数组进行排序,按照年龄进行升序排序
   bubbleSort(heroArray,len);
   cout<<"排序后的打印:"<<endl;
   
   //4、将排序后结果打印输出
   printHero(heroArray,len);
 
    return 0;
}

6. Small project: address book management system

//
// Created by mac on 2021/2/8.
//


//封装函数显示该界面 如 void showMenu()
//在 main 函数中调用封装好的函数
#include <iostream>
using namespace std;
#include <string>
#define MAX 1000
#include <unistd.h>

//3、设计联系人和通讯录的结构体
//设计联系人的结构体
struct Person
{
    //姓名
    string m_Name;

    //性别:男1 女2
    int m_Sex;

    //年龄
    int m_Age;

    //电话
    string m_Phone;

    //住址
    string m_Addr;
};

//通讯录的结构体
struct Addressbook
{
    //通讯录中保存的联系人数组
    struct Person personArray[MAX];

    //通讯录中当前记录联系人个数
    int m_Size;
};

//1、菜单界面
void showMenu()
{
    cout<<"***********************"<<endl;
    cout<<"***** 1、添加联系人 *****"<<endl;
    cout<<"***** 2、显示联系人 *****"<<endl;
    cout<<"***** 3、删除联系人 *****"<<endl;
    cout<<"***** 4、查找联系人 *****"<<endl;
    cout<<"***** 5、修改联系人 *****"<<endl;
    cout<<"***** 6、清空联系人 *****"<<endl;
    cout<<"***** 0、退出通讯录 *****"<<endl;
    cout<<"***********************"<<endl;
}

//5、利用地址传递,可以修饰实参
void addPerson(struct Addressbook * abs)
{
    //判断通讯录是否已满,如果满了就不再添加
    if(abs->m_Size == MAX)
    {
        cout<<"通讯录已满,无法添加!"<<endl;
        return;
    }
    else
    {
        //添加具体联系人

        //添加姓名
        string name;
        cout<<"请输入姓名:"<<endl;
        cin>>name;
        abs->personArray[abs->m_Size].m_Name = name;

        //添加性别
        cout<<"请输入性别:"<<endl;
        cout<<"1--男;2--女"<<endl;
        int sex = 0;
        while(true)
        {
            cin>>sex;
            //输入1或者2正确退出循环,输入其他则重新输入
            if (sex == 1 || sex == 2)
            {
                abs->personArray[abs->m_Size].m_Sex = sex;
                break;
            }
            cout<<"输入有误,请从新输入!"<<endl;
        }

        //添加年龄
        cout<<"请输入年龄:"<<endl;
        int age = 0;
        cin>>age;
        abs->personArray[abs->m_Size].m_Age = age;

        //添加电话
        cout<<"请输入联系电话:"<<endl;
        string phone;
        cin>>phone;
        abs->personArray[abs->m_Size].m_Phone = phone;

        //添加住址
        cout<<"请输入家庭住址:"<<endl;
        string addr;
        cin>>addr;
        abs->personArray[abs->m_Size].m_Addr = addr;

        //更新通讯录人数(关键)
        abs->m_Size++;

        cout<<"添加成功"<<endl;

        //pause();//请按任意键继续   mac下似乎不能用这两个函数,此问题暂时还为解决
        //system("clear");//清屏操作
    }
}

//6、显示所有的联系人
void showPerson(struct Addressbook * abs)
{
    //判断通讯录中人数是否为0,如果为0,提示记录为空
    //如果不为0,显示记录的联系人信息
    if(abs->m_Size == 0)
    {
        cout<<"当前联系人为空"<<endl;
    }
    else
    {
        for(int i=0 ; i<abs->m_Size ; i++)
        {
            cout<<"姓名:"<<abs->personArray[i].m_Name<<"\t";
            cout<<"性别:"<<(abs->personArray[i].m_Sex ==1 ? "男":"女")<<"\t";//关键
            cout<<"年龄:"<<abs->personArray[i].m_Age<<"\t";
            cout<<"电话:"<<abs->personArray[i].m_Phone<<"\t";
            cout<<"住址:"<<abs->personArray[i].m_Addr<<endl;
        }
    }

    //pause();//按任意键继续
    //system("clear");//请屏
}

//7、检测联系人是否存在,如果存在,返回联系人所在数组中的具体位置,不存在返回-1
//参数1 通讯录 参数2 对比姓名
int isExist(struct Addressbook * abs , string name)
{
    for(int i=0 ; i<abs->m_Size ; i++)
    {
        //找到用户输入的姓名了
        if(abs->personArray[i].m_Name == name)
        {
            return i;//找到了,返回这个人在数组中的下标编号
        }
         return -1;//如果遍历结束都没有找到,返回-1
    }
}

//8、删除指定联系人
void deletePerson(struct Addressbook *abs)
{
    cout<<"请输入您要删除的联系人"<<endl;

    string name;
    cin>>name;

    //ret == -1 未查到
    //ret != -1 查到了
    int ret = isExist(abs,name);

    if(ret != -1)
    {
        for(int i=0 ; i<abs->m_Size ; i++)
        {
            //数据前移
            abs->personArray[i] = abs->personArray[i+1];//只能按顺序删除,把后一个数据覆盖调前一个数据,此代码有缺陷
        }
        abs->m_Size--;//更新通讯录中的人员数
        cout<<"删除成功"<<endl;
    }
    else
    {
        cout<<"查无此人"<<endl;
    }

    //pause();
    //system("clear");

}

//9、查找指定联系人:此代码有缺陷,必须先创建一个联系人信息才能执行完整代码
void findPerson(struct Addressbook * abs)
{
    cout<<"请输入您要查找的联系人"<<endl;

    string name;
    cin>>name;

    //判断指定的联系人是否存在通讯录
    int ret = isExist(abs,name);

    if(ret != -1)//找到联系人
    {
        cout<<"姓名:"<<abs->personArray[ret].m_Name<<"\t";
        cout<<"性别:"<<abs->personArray[ret].m_Sex<<"\t";
        cout<<"年龄:"<<abs->personArray[ret].m_Age<<"\t";
        cout<<"电话:"<<abs->personArray[ret].m_Phone<<"\t";
        cout<<"住址:"<<abs->personArray[ret].m_Addr<<endl;
    }
    else
    {
        cout<<"查无此人"<<endl;
    }

    //pause();
    //system("clear");
}

//10、修改指定联系人的信息
void modifyPerson(struct Addressbook * abs)
{
    cout<<"请输入您要修改的联系人"<<endl;
    string name;
    cin>>name;

    int ret = isExist(abs,name);
    if(ret != 1) {
        //修改姓名
        cout << "请输入姓名:" << endl;
        string name;
        cin >> name;
        abs->personArray[ret].m_Name = name;

        //修改性别
        cout << "请输入性别:" << endl;
        cout << "1--男" << endl;
        cout << "2--女" << endl;
        int sex = 0;

        while (true)
        {
            cin >> sex;
            if (sex == 1 || sex == 2)
            {
                abs->personArray[ret].m_Sex = sex;
                break;
            }
            cout<<"输入有误,请重新输入"<<endl;
        }

        //修改年龄
        cout<<"请输入年龄:"<<endl;
        int age = 0;
        cin>>age;
        abs->personArray[ret].m_Age = age;

        //修改电话
        cout<<"请输入联系电话:"<<endl;
        string phone;
        cin>>phone;
        abs->personArray[ret].m_Phone = phone;

        //修改住址
        cout<<"请输入家庭住址:"<<endl;
        string addr;
        cin>>addr;
        abs->personArray[ret].m_Addr = addr;
    }
    else
    {
        cout<<"查无此人"<<endl;
    }
}

//11、清空所有的联系人
void cleanPerson(struct Addressbook * abs)
{
    cout<<"是否确定清空?"<<endl;
    cout<<"1 -- 是"<<endl;
    cout<<"2 -- 否"<<endl;

    int num = 0;

    while(true)
    {
        cin >> num;
        if (num == 1)
        {
            abs->m_Size = 0;//将当前记录联系人的数量置为0,做逻辑清空操作
            cout << "通讯录已清空" << endl;
            break;
        }
        else if (num == 2)
        {
            cout << "停止清空" << endl;
            break;
        }
        cout<<"输入有误,请重新输入"<<endl;
    }
    //pause();
    //system("clear");
}

 int main()
 {

    //4、创建通讯录结构体变量
    struct Addressbook abs;

    //初始化通讯录中当前人员个数
    abs.m_Size = 0;

    int select = 0;//2、创建用户选择输入的变量

    while(true)
    {

        //1、菜单调用
        showMenu();

        //2、创建用户选择输入的变量
        cin>>select;

        //只有选择0的时候才退出,其他选择则继续循环
        switch (select) {
            case 1: //1、添加联系人
                addPerson(&abs);//5、增加联系人。利用地址传递,可以修饰实参
                break;

            case 2://2、显示联系人
                showPerson(&abs);//6、显示所有的联系人
                break;

            case 3://3、删除联系人

            /*
             * 测试代码
            {
                cout << "请输入需要删除的联系人姓名:" << endl;
                string name;
                cin >> name;
                if (isExist(&abs, name) == -1) {
                    cout << "查无此人" << endl;
                } else {
                    cout << "找到此人" << endl;
                }

            }
            */
                deletePerson(&abs);//7和8、删除指定联系人
                break;

            case 4://4、查找联系人
                findPerson(&abs);//9、查找指定联系人
                break;
            case 5://5、修改联系人
                modifyPerson(&abs);//10、修改指定联系人的信息
                break;
            case 6://6、清空联系人
                cleanPerson(&abs);//11、清空所有的联系人
                break;
            case 0://0、退出通讯录
                cout << "欢迎下次使用" << endl;
                pause();
                return 0;
            default:
                break;
        }

    }

}

7. The memory model of the program

7.1, memory area four

7.1.1. Concept

When the C++ program is executed, the general direction of memory is divided into 4 areas

- Code area (binary): store the binary code of the function body, managed by the operating system

- Global area (storage): store global variables, static variables and constants (const-modified global variables and string constants are stored in the constant area)

- Stack area (function parameters, local): automatically allocated and released by the compiler, storing function parameter values, local variables, etc.

- Heap area (coder allocation): allocated and released by the programmer, if the programmer does not release, it will be reclaimed by the operating system at the end of the program

7.1.2. Significance (different regions have different life spans)

The data stored in different areas are endowed with different life cycles, giving us more flexible programming

7.2. Before the program runs

After the program is compiled, an exe executable program is generated, which is divided into two areas before the program is executed

7.2.1, code area

​ Store the machine instructions executed by the CPU

​ The code area is shared , and programs that are frequently executed only need to have one code in memory

​ The code area is read-only , preventing the program from accidentally modifying its instructions

7.2.2. Global zone

​The data in this area is released by the operating system after the program ends

#include <iostream>

using namespace std;

//全局变量(凡函数体外的变量称为全局变量)
int g_a = 10;

//const修饰的全局变量称为全局常量
const int c_g_a = 10;

int main()
{
    
    //全局区:全局变量、静态变量、常量
    
    //创建普通局部变量(在函数体内的变量称为局部变量)
    int a = 10;
    cout<<"局部变量a的地址为:"<<&a<<endl;
    cout<<"全局变量g_a的地址为:"<<&g_a<<endl;
    
    //静态变量(在普通变量前加static,属于静态变量)
    static int s_a = 10;
    cout<<"静态变量s_a的地址为:"<<&s_a<<endl;
    
    //常量
    //字符串常量
    cout<<"字符串常量的地址为:"<<&"字符串常量地址"<<endl;
    
    //const修饰的变量
    //const修饰的全局变量
    cout<<"全局常量 c_g_a的地址为:"<<&c_g_a<<endl;
    
    //const修饰的局部变量称为局部常量
    const int c_l_a = 10;//c代表const l代表local g代表global
    cout<<"局部常量 c_l_a的地址为:"<<&c_l_a<<endl;
    
    return 0;
}

7.3. After the program runs

7.3.1. Stack area

//由编译器自动分配释放, 存放函数的参数值,局部变量等
​//注意事项:不要返回局部变量的地址,栈区开辟的数据由编译器自动释放

#include <iostream>
using namespace std;

int* func(int b)//形参数据也会放在栈区
{
    b = 100;
    int a = 10;//局部变量,存放在栈区,栈区的数据在函数执行完成后自动释放
    return &a;//不能返回局部变量的地址
}

int main()
{
    int * p = func(1);
    cout<<*p<<endl;//第一次可以打印正确的数字是因为编译器做了保留
    cout<<*p<<endl;//第二次这个数据就不再保留了

    return 0;
}

7.3.2. Heap area

//由程序员分配释放,若程序员不释放,程序结束时由操作系统回收
//在C++中主要利用new在堆区开辟内存

#include <iostream>
using namespace std;

int * func()//形参数据也会放在栈区
{
    //利用new关键字可以将数据开辟到堆区
    //指针,本质也是局部变量,放在栈上;指针保存的数据是放在堆区
    int * p = new int(10);
    return p;
}

void test01()
{
    int * p = func();
    cout<<*p<<endl;
    cout<<*p<<endl;
    cout<<*p<<endl;
    cout<<"---------"<<endl;
    //1、堆区开辟的数据,由程序员手动开辟,手动释放,释放利用关键字 ==delete==
    delete p;
    
    cout<<*p<<endl;//内存已经被释放,再次访问就是非法操作,会报错
}

//2、在堆区利用new开辟数组
void test02()
{
    //创建10整形数据的数组,在堆区
    int * arr = new int[10];
    
    for(int i=0 ; i<10 ; i++)
    {
        arr[i] = i+100;//给10个元素赋值 100~109
    }
    
    for(int i=0 ; i<10 ; i++)
    {
        cout<<arr[i]<<endl;
    }
    
    //释放堆区数组
    //释放数组的时候要加[]才可以
    delete[] arr;
}

int main()
{
    //在堆区开辟数据
    //int * p = func();
    test01();
    
    test02();

    //
    
    return 0;
}

8. Quote

Function: alias the variable

8.1. Basic grammar and precautions for citations

#include <iostream>
using namespace std;

int main()
{
    
    //语法: 数据类型 &别名 = 原名
    int a = 10;
    //创建引用
    int &b = a;
    //int &b;//1、错误,必须初始化
    
    //2、引用在初始化后不可以改变
    int c = 30;

    b = c;//赋值操作,而不是更改引用
    
    cout<<"原名:"<<a<<endl;
    cout<<"别名:"<<b<<endl;
    cout<<"c的值:"<<c<<endl;
    cout<<"--------"<<endl;
    
    b = 20;
    cout<<"原名:"<<a<<endl;
    cout<<"别名:"<<b<<endl;
    
    return 0;
}

8.2. References as function parameters

Function: When a function passes parameters, you can use the reference technique to let the formal parameters modify the actual parameters

Advantages: can simplify the pointer to modify the actual parameter

#include <iostream>
using namespace std;

void Swap(int &a,int &b)//其实 &a 是 a 的别名,&b 是 b 的别名
{
    int temp = a;
    a = b;
    b = temp;
}

int main()
{
    int a = 1;
    int b = 2;
    
    Swap(a,b);//引用传递和地址传递一样,都可以形参修饰实参
    
    cout<<"a = "<<a<<endl;
    cout<<"b = "<<b<<endl;

    return 0;
}

8.3, reference as the return value of the function

Role: references can exist as return values ​​of functions

Usage: function call as lvalue

#include <iostream>
using namespace std;

//引用做函数的返回值
//1、注意:不要返回局部变量的引用
int& test01()
{
    int a = 10;//局部变量存放在四区中的 栈区
    return a;
}

//2、用法:函数的调用可以作为左值
int& test02()
{
    static int a = 10;//静态变量,存放在全局区,全局区上的数据在程序结束后系统释放
    return a;
}

int main()
{
    int &ref1 = test01();
    
    cout<<"ref1 = "<<ref1<<endl;//第一次结果正确,是因为编译器做了保留
    cout<<"ref1 = "<<ref1<<endl;//第二次结果错误,是因为a的内存已经释放
    cout<<"------"<<endl;

    int &ref2 = test02();
    
    cout<<"ref2 = "<<ref2<<endl;
    cout<<"ref2 = "<<ref2<<endl;
    
    test02() = 1000;//如果函数的返回值是引用,这个函数调用可以作为左值(左边的值)
    
    cout<<"-------"<<endl;
    cout<<"ref2 = "<<ref2<<endl;
    cout<<"ref2 = "<<ref2<<endl;
    
    
    return 0;
}

8.4. The nature of citations

Essence: The internal implementation of C++ is a pointer constant

Conclusion: C++ recommends using reference technology, because the syntax is convenient, and the essence of reference is a pointer constant, but all pointer operations are done for us by the compiler

8.5, constant reference

#include <iostream>
using namespace std;

void showValue(const int &val)//const修饰形参,防止误操作
{
    //val = 1000;//加了const防止形参改变实参 assignment:分配 ,reference:引用
    cout<<"val="<<val<<endl;
}

int main()
{
    
    //作用:常量引用主要用来修饰形参,防止误操作
    int a = 10;
    //int &ref = 10;//10是在常量区,引用必须引一块合法的内存空间
    
    //加上const之后编译器将代码修改 int temp = 10;const int & ref = temp;
    //const int &ref = 10;
    //ref = 20;//加入const之后变为只读,不可以修改
    
    showValue(a);
    cout<<"a = "<<a<<endl;
    
    return 0;
}

Guess you like

Origin blog.csdn.net/qq_42535298/article/details/122796753