C++(3) 引用、const、new、内联函数以及重载

文章目录

      • C++
        • 1. C++ 相较于 C 语言的增强
          • 1.1 引用 Reference
            • 1.1.1 引用基础案例
            • 1.1.2 一个变量可以有多个引用
            • 1.1.3 引用在函数参数中的使用
            • 1.1.4 指针引用
          • 1.2 const 关键字
            • 1.2.1 基本特征
            • 1.2.2 使用 const 代替 #default 无参数宏
          • 1.3 new 和 delete
            • 1.3.1 案例
            • 1.3.2 结构体空间内容操作
          • 1.4 内联函数
          • 1.5 函数参数补充说明
            • 1.5.1 关于无参数函数
            • 1.5.2 函数的默认参数
            • 1.5.3 重载overload 【重点】

C++

1. C++ 相较于 C 语言的增强
1.1 引用 Reference
1.1.1 引用基础案例
#include 

using namespace std;

int main(int argc, char const *argv[])
{
    int num =10;

    /*
    C++ 特定的数据形式【引用】需要使用的【标记】标点符号
        &
    定义了一个 int 类型的引用,引用名称为 ref,使用 num 赋值当前引用

    可以认为
        1. ref 是一个引用
        2. ref 是 num 变量的别名
    */
    int & ref = num;

    cout << "num : " << num << endl; // 10
    cout << "ref : " << ref << endl; // 10

    cout << "---------------------------------" << endl;

    num = 300;
    cout << "num : " << num << endl; // 300
    cout << "ref : " << ref << endl; // 300
    
    cout << "---------------------------------" << endl;

    num = 20000;
    cout << "num : " << num << endl; // 2000
    cout << "ref : " << ref << endl; // 2000

    return 0;
}
1.1.2 一个变量可以有多个引用
#include 

using namespace std;

int main(int argc, char const *argv[])
{
    int num = 30;

    int &ref1 = num;
    int &ref2 = num;
    int &ref3 = num;

    cout << "num : " << num << endl;
    cout << "ref1 : " << ref1 << endl;
    cout << "ref2 : " << ref1 << endl;
    cout << "ref3 : " << ref1 << endl;
    cout << "------------------------------" << endl;

    ref3 = 10000;
    cout << "num : " << num << endl;
    cout << "ref1 : " << ref1 << endl;
    cout << "ref2 : " << ref1 << endl;
    cout << "ref3 : " << ref1 << endl;

    return 0;
}
1.1.3 引用在函数参数中的使用
#include 

using namespace std;

//值传递
void swap1(int n1, int n2);

// 地址传递
void swap2(int *p1, int *p2);

/*
引用传递
当前函数所需的参数类型是引用类型

@param r1 int 类型引用
@param r2 int 类型引用
*/
void swap3(int &r1, int &r2);

int main(int argc, char const *argv[])
{
    int num1 = 20;
    int num2 = 30;

    swap1(num1, num2);
    cout << "num1 : " << num1 << endl; // 20
    cout << "num2 : " << num2 << endl; // 30
    cout << "----------------------------" << endl;

    swap2(&num1, &num2);
    cout << "num1 : " << num1 << endl; // 30
    cout << "num2 : " << num2 << endl; // 20
    cout << "----------------------------" << endl;

    /*
    引用的优势:
        1. 相较于指针方式省空间,引用的不占用额外的内存空间
        指针变量占用内存 8 个字节( 64 位系统)
        2. 引用不会有额外运算符使用,操作简单,使用方便
        3. 引用效率高于指针
    
    swap3(num1, num2);
        参数赋值相当于
            int & r1 = num1;
            int & r2 = num2;
    */
    swap3(num1, num2);
    cout << "num1 : " << num1 << endl; // 20
    cout << "num2 : " << num2 << endl; // 30

    return 0;
}

void swap1(int n1, int n2)
{
    int temp = n1;
    n1 = n2;
    n2 = temp;
}

void swap2(int *p1, int *p2)
{
    int temp = *p1;
    *p1 = *p2;
    *p2 = temp;
}

void swap3(int &r1, int &r2)
{
    int temp = r1;
    r1 = r2;
    r2 = temp;
}
1.1.4 指针引用
#include 
#include 
#include 
#include 

using namespace std;

struct Student
{
    int id;
    int name[32];
    int age;
};

/*
当前函数所需参数为 二级指针,需要修改外部指针变量存储的数据内容
如果提供的参数类型为一级指针,有且只能修改当前指针指向的数据空间内容,
无法修改当前指针变量存储的数据情况。提供二级指针,可以修改当前指针变量
存储的数据内容。
*/
void alloc_new_memory(Student **stu);

/*
当前函数参数为【Student 类型指针引用】,可以直接传入 Student *
指针类型

降低代码的逻辑复杂度,提升代码效率,同时节约内存
*/
void alloc_new_memory_by_reference(Student * & stu);

int main(int argc, char const *argv[])
{
    Student *stu = (Student *)malloc(sizeof(Student));
    memset(stu, 0, sizeof(Student));

    cout << "stu : " << stu << endl;

    // 当前函数所需参数为 Student ** 二级指针,需要取地址当前 Student * 指针变量
    alloc_new_memory(&stu);
    
    cout << "stu : " << stu << endl;

    // 当前函数所需参数为 Student * & 引用,可以直接提供 Student * 指针
    alloc_new_memory_by_reference(stu);

    cout << "stu : " << stu << endl;

    free(stu);

    /*
    利用函数修改当前 Stu 的指向
    */
    return 0;
}

void alloc_new_memory(Student **stu)
{
    free(*stu);
    int *arr = (int *)malloc(sizeof(int) * 10);
    *stu = (Student *)malloc(sizeof(Student));
    memset(*stu, 0, sizeof(Student));

    free(arr);
}

void alloc_new_memory_by_reference(Student * & stu)
{
    free(stu);
    int *arr = (int *)malloc(sizeof(int) * 10);
    stu = (Student *)malloc(sizeof(Student));
    memset(stu, 0, sizeof(Student));

    free(arr);
}
1.2 const 关键字
1.2.1 基本特征

基本变量 const 修饰

#include 

const int num = 20;

cout << "num : " << num << endl;

/*
num = 20;

error: assignment of read-only variable 'num'
const 修饰当前变量,可以简单认为当前变量为常量
后续无法进行赋值操作
当前 num 只读【read-only】
*/

const int * p, const 修饰限制指针指向数据空间

const int num = 20;
/*
const int num 变量地址,对应的指针类型参数为 const int *,
无法赋值给一个 int * 指针
*/
const int *p = #


/*
*p = 20; ERRPR 表达式必须使可修改的左值C/C++(137)
*p ==> num 而 num 使 read-only 制度变量
p = &num1; const int *p 指针指向的数据内容空间不可以修改,
但是存储的地址可以修改
*/
p = &num1;
cout << "*p = " << *p << endl;

const int * const p, const 修饰限制指针指向数据内容空间,同时 const 修饰限制指针变量数据存储

const int num1 = 100;

const int *const p1 = #
/*
*p1 = 20;
p1 = &num1;
*p1 assignment of read-only location ‘*(const int*)p1’
指向空间数据内容无法修改,是一个常量
p1 error: assignment of read-only variable ‘p1’
p1 也是一个常量,指针常量存储地址不可以修改
*/

int * const p const 修饰限制指针变量数据存储

int num2 = 200;
int *const p2 = &num2;
int num3 = 100;
/*
p2 指向数据空间内容可以修改,但是存储的地址不能修改
*/
*p2 = 1000; // √
p2 = &num3; // ×

return 0;
1.2.2 使用 const 代替 #default 无参数宏
#include 

/*
宏只可以做简单的替换,不会考虑
    1. 数据类型问题
    2. 语法出错问题
*/
#define COUNT 10

/*
const 修饰变量作为常量使用,具有的优点:
    1. 具备数据类型特征,可以检查数据类型情况
    2. 有一定的语法限制,可以前置错误情况
    3. 使用全局变量形式完成 const 常量限制,功能性和宏类似,安全性更好
*/
const int num = 10;

using namespace std;

int main(int argc, char const *argv[])
{
    cout << "count : " << COUNT << endl; // 10
    cout << "num : " << num << endl; // 10
     
    return 0;
}
1.3 new 和 delete
1.3.1 案例

C++ 用于动态分配内存得关键字,效果 C 语言 malloc 、calloc 、realloc 、free 一致

#include 
#include 
#include 
#include 

using namespace std;

int main(int argc, char const *argv[])
{
    /*
    C 语言内存申请方式和释放方式
    */
    int *arr = (int *)malloc(sizeof(int) * 10);
    memset(arr, 0, sizeof(int) * 10);

    free(arr);
    arr = NULL;

    /*
    C++ 内存申请方式和释放方式
    */
    int *arr2 = new int[10];
    memset(arr2, 0, sizeof(int) * 10);

    // 使用
    for (int i = 0; i < 10; i++)
    {
        arr2[i] = i * 2;
    }
    for (int i = 0; i < 10; i++)
    {
        cout << "arr[" << i << "] = " << arr2[i] << endl;
    }
    
    delete arr2;
    arr2 = NULL;

    return 0;
}
1.3.2 结构体空间内容操作
#include 

using namespace std;

struct Student
{
    int id;
    string name;
    int age;
};

int main(int argc, char const *argv[])
{
    /*
    new 申请内存【堆区】空间,创建一个可以存储 Student 
    数据的内存空间,返回对应空间首地址
    */
    Student * stu = new Student;

    stu->id = 1;
    stu->name = "张三";
    stu->age = 3;

    cout << "ID : " << stu->id 
        << ", Name : " << stu->name 
        << ", Age : " << stu->age << endl;

    delete stu;
    stu = NULL;

    return 0;
}
1.4 内联函数
#include 

using namespace std;

/*
有参宏,可以完成一定的替代代码内容,但是有以下问题:
    1. 没有严格的数据类型限制,没有数据类型检查
    2. 替换结果会因为宏内容导致结果不一致,无法满足程序的期望
*/
// 不加小括号执行时会出现计算与预期结果不一致
#define ADD(a, b) a + b

/*
首先这里时一个函数,并且是有参数有返回值的函数
函数声明有一个关键字修饰 inline

inline 函数可以提升一定的开发效率,在代码执行之前
inline 函数会替代调用位置内容
    替代之前,会检查一下内容:
    1. 函数名
    2. 参数数据类型
    3. 整个 inline 函数结果是一个整体
*/
inline int add(int a, int b)
{
    return a + b;
}

int main(int argc, char const *argv[])
{
    int ret = ADD(10, 20) * 10; // 10 + 20 * 10 ==> 210 非预期结果
    cout << "ret : " << ret << endl;

    ret = add(10, 20) * 10; // (10 + 20) * 10 ==> 300 预期结果
    cout << "ret : " << ret << endl;

    return 0;
}
1.5 函数参数补充说明
1.5.1 关于无参数函数

C 语言中,如果按照严格的代码规范,无参数函数,小括号需要使用 void 占位

void test(void);
#include 

// C 语言中,如果按照严格的代码规范,无参数函数,小括号需要使用 void 占位
void test(void);

int main(int argc, char const *argv[])
{
    test(); // 中医博大精深!

    return 0;
}

void test(void)
{
    printf("中医博大精深!!\n");
}

C++ 语言中,不需要 void 占位

void test();
#include 

using namespace std;

void test();

int main(int argc, char const *argv[])
{
    test(); // 中医博大精深!!
    // 不可传入参数
    // test(10);

    return 0;
}

void test()
{
    cout << "中医博大精深!!" << endl;
}
1.5.2 函数的默认参数
#include 

using namespace std;

/*
声明位置中有一个参数存在默认值
*/
void test(int num1, int num2 = 10);

int main(int argc, char const *argv[])
{
    // 如果函数参数带有默认值,对应函数可以不提供实际参数
    test(100);
    cout << "-----------------" << endl;
    test(100, 200);

    return 0;
}

/*
函数的实现位置,不需要再次明确函数参数默认值
*/
void test(int num1, int num2)
{
    cout << "num1 : " << num1 << endl;
    cout << "num2 : " << num2 << endl;
}
1.5.3 重载overload 【重点】
#include 

using namespace std;

void test();

// 函数返回值类型不作为函数的唯一标记,【语法错误】函数重复定义
// 无法通过函数名(实际参数数据类型) 来明确目标函数是哪一个
// int test();

/*
在同一区域范围内,同一个命名空间、同一个文件(.h .cpp)、同一个类内
如果函数的名称一致,但是函数的形式参数列表数据类型、数据顺序、数据个数不同
【函数的重载】

要求:
    1. 在同一个区域范围以内
    2. 函数名必须一致
    3. 函数的形式参数列表必须不一致
*/
void test(int num);

int main(int argc, char const *argv[])
{
    test();
    test(100);

    return 0;
}

void test()
{
    cout << "无参数 test" << endl;
}

void test(int num)
{
    cout << "num : " << num << endl;
}

你可能感兴趣的:(c++,开发语言,c语言,学习,学习方法)