C++基础(二) C++对C语言的拓展

1 引用

1.1 引用的基本概念
#include <stdio.h>

#include "iostream"
using namespace std;
int main()
{
    int a = 10;
    int *p = &a;
    *p = 20;
    
    cout << "a = " << a << endl;
    
   //1 &符号前面有数据类型时,才表示引用,不带数据类型的皆为取地址
    int &b = a; //b可以理解为a的别名
    
    b = 40;
    
    //2 c++提供了一种对变量间接操作的方式 ----> 引用
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
    
    cout << "&a = " << &a << endl;
    cout << "&b = " << &b << endl;
    
    //3 引用一定要初始化 否则报错 Error: Declaration of reference variable 'c' requires an initializer
    //int &c;
    
    //4  可对引用再次引用
    int &d = b;
    cout << "&d = " << &d << endl;
    cout << "d = " << d << endl;
    
    return 0;
}

打印结果

a = 20
a = 40
b = 40
&a = 0x7ffeefbff528
&b = 0x7ffeefbff528
&d = 0x7ffeefbff528
d = 40
1.2 引用作为函数参数
#include <iostream>
using namespace std;

struct Teacher{
    int id;
    char name[64];
};

//1 局部临时变量,会发生值拷贝 并不会改变函数的参数值
void printT1(Teacher t){
    cout << "id = " << t.id << endl;
    cout << "name = " << t.name << endl;
    t.id = 100;
}

//2 通过指针间接修改变量的值
void printT2(Teacher *t){
    cout << "id = " << t->id << endl;
    cout << "name = " << t->name << endl;
    t->id = 100;
}

//3 通过引用来间接修改变量的值
void printT3(Teacher &t){
    cout << "id = "  << t.id << endl;
    cout << "name = " << t.name << endl;
    t.id = 1000;
}

void swap1(int a, int b){
    int temp = a;
    a = b;
    b = temp;
}

void swap2(int *a, int *b){
    int temp = *a;
    *a = *b;
    *b = temp;
}

void swap3(int &a, int &b){
    int temp = a;
    a = b;
    b = temp;
}
int main(void){
    
    Teacher t1 = {1, "张三"};
    printT1(t1);
    cout << t1.id << endl;
    
    printT2(&t1);
    cout << t1.id << endl;
    
    printT3(t1);
    cout << t1.id << endl;
    
    
    int a = 10;
    int b = 20;
    
    swap1(a, b);
    cout << "a = " << a << " b = " << b << endl;
    
    swap2(&a, &b);
    cout << "a = " << a << " b = " << b << endl;
    
    swap3(a, b);
    cout << "a = " << a << " b = " << b << endl;
    return 0;
}

打印结果

id = 1
name = 张三
1
id = 1
name = 张三
100
id = 100
name = 张三
1000
a = 10 b = 20
a = 20 b = 10
a = 10 b = 20
1.3 引用的本质
#include <iostream>

using namespace std;

struct Teacher{
    int id;
    char name[64];
};

struct TypeA{
    int *a;
};

struct TypeB{
    double &a;
};


//用于说明指针的引用都是占用8个字节
void reSize(){
    cout << "sizeof(TypeA) = " << sizeof(TypeA) << endl;
    cout << "sizeof(TypeB) = " << sizeof(TypeB) << endl;
}


//用于说明引用相当于常指针
void modifyA(int * const a){
    *a = 100;
}

void modifyB(int &a){
    //a实际上是一个常量指针,这里给a赋值,编译器会有一个隐形的操作 *
    a = 1000;
}

void test(){
    int value = 20;
    Teacher t1 = {1, "张三"};
    
    modifyA(&value);
    cout << "value = " << value << endl;
    
    modifyB(value);
    cout << "value = " << value << endl;
}

int main(void){
    int a = 10;
    int b = 20;
    
    const int c = 10;
    //c = 20;//Error:Cannot assign to variable 'c' with const-qualified type 'const int'
    
    //1 引用必须初始化 (由此猜想引用可能是常量)
    int &re = a;
    
    //2 不管引用是什么类型,都是8个字节。和指针的大小一样 (由此猜想引用可能是指针类型)
    reSize();
    
    //示例引用和常指针对比
    test();
    
    //3 总结:
    //引用原理: 可以将引用理解为常量指针
    //理解引用: 可以将引用理解为变量的别名
    
    return 0;
}

打印结果

sizeof(TypeA) = 8
sizeof(TypeB) = 8
value = 100
value = 1000
1.4 引用作为函数返回值
#include <iostream>
using namespace std;

int getA1(){
    int a = 10;
    return a;
}

int& getA2(){
    int a = 20;
    return a;
}

int &getB(){
    static int b = 100;
    return b;
}

int main(void){
    int a = 0;
    a = getA1();
    cout << "a = " << a << endl;
    
    a = getA2();
    cout << "a = " << a << endl;
    
    //1 当函数返回值是一个局部变量的引用的时候,不能再用引用来接收
    int &r_a = getA2();//禁止用引用来接收 没有值拷贝动作
    cout << "r_a = " << r_a << endl;
    
    //2 当函数返回值是一个静态变量的引用时,可以用引用来接收
    int &r_b = getB();
    cout << "r_b = " << r_b << endl;
    
    //3 此时r_b 就是getB()方法中b的别名
    r_b = 2000;
    
    int b = getB();
    cout << "b = " << b << endl;
    
    //4 当引用作为函数的返回值时,只要这个引用是合法的,就可以当左值
    getB() = 3000;
    return 0;
}

打印结果

a = 10
a = 20
r_a = 32767
r_b = 100
b = 2000
1.5 指针引用
#include <iostream>
using namespace std;

struct Teacher{
    int id;
    char name[64];
};

int getTeacher_01(Teacher **pp){
    Teacher *p = NULL;
    p = (Teacher *)malloc(sizeof(Teacher));
    
    if(p == NULL){
        cout << "error p == NULL" << endl;
    }
    
    memset(p, 0, sizeof(Teacher));
    p->id = 30;
    
    *pp = p;
    return 0;
}

int getTeacher02(Teacher* &tr){
    tr = (Teacher *) malloc(sizeof(Teacher));
    if(tr == NULL){
        cout << "error tr = NULL" << endl;
        return -1;
    }
    tr->id = 40;
    strcpy(tr->name, "张三");
    return 0;
}

void freeTeacher_01(Teacher* &tr){
    if(tr != NULL){
        free(tr);
        tr = NULL;
    }
}

void freeTeacher_02(Teacher **pp){
    if(pp == NULL){
        return;
    }
    
    Teacher *p = *pp;
    if(p != NULL){
        free(p);
        *pp = NULL;
    }
}

int main(void){
    Teacher *tp  = NULL;
    
    //1 通过二级指针给一级指针赋值
    getTeacher_01(&tp);
    cout << "tp = " <<  tp << endl;
    cout << "tp->id = " <<  tp->id << endl;
    
    //2 通过指针引用给指针赋值
    getTeacher02(tp);
    cout << "tp->name = " <<  tp->name << endl;
    
    //3 两种释放方式都可以
    //freeTeacher_01(tp);
    freeTeacher_02(&tp);
    cout << "tp = " <<  tp << endl;
    
    return 0;
}

打印结果

tp = 0x100505420
tp->id = 30
tp->name = 张三
tp = 0x0
1.6 const引用
#include <iostream>
using namespace std;

void printX(const int &re){
    cout << " re = " << re << endl;
}

int main(void){
    
    //1 如果被引用的是const常量,必须用const引用来接收
    const int a = 10;
    const int &b = a;

    //int& re_2 = 10;//error:Non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'
    
    //2 引用字面量必须加const关键字,这是因为字面量本身没有地址,所以引用无法对字面量取地址
    const int& re_2 = 10;
    cout << "re_2 = " << re_2 << endl;
    
    return 0;
}

打印结果

re_2 = 10

2 内联函数

#include <iostream>
using namespace std;

inline int func(int a, int b){
    return (a < b ? a : b);
}

#define MAX_VALUE(a, b) ((a) < (b) ? (a) : (b))

inline void printValue(int a, int b);

int main(){
    //1 调用内联函数的时候,和普通函数的区别是没有函数压栈和出栈的开销
    int value = func(10, 20);
    cout << "value = " << value << endl;
    //inline函数会将func全部展开
//    {
//      return (a < b ? a : b);
//    }
    
    
   
    //2 内联函数和宏函数的区别
    //内联函数:所有的编译器词法分析和校验都有,是编译器处理的
    //宏函数: 由预处理器处理,没有像函数一样的校验
    int a = 50;
    int b = 20;
    
    int c = MAX_VALUE(a, b);
    cout << "c = " << c << endl;
    
    //3 如果函数声明用了inline关键字,但是函数定义没有写inline,编译器仍然不会按inline函数处理
    printValue(a, b);
    
    //4 适用场景:函数体很小,且被频繁的调用
    return 0;
}

void printValue(int a, int b){
    cout << "a = " << a << ", b = " << b << endl;
}

打印结果

value = 10
c = 20
a = 50, b = 20

3 默认参数和占位参数

//2 默认参数必须是从右向左设置,一旦有了默认参数,则右边的参数都必须有默认值
//error:Missing default argument on parameter 'high'
//int volume(int len, int width = 20, int high){
int volume(int len, int width = 20, int high = 30){
    return len * width * high;
}

int main(){
    int x = 10;
    
    //1 第二个参数是默认参数,可传可不传
    func(x);
    func(x, 20);
    
    return 0;
}

打印结果

func = 10,a = 100
func = 10,a = 20

4 函数重载

4.1 重载规则
#include <iostream>
using namespace std;

void func(int a){
    cout << "func(int a)" << endl;
}

//重载1:方法名相同,参数类型不同
void func(char a){
    cout << "func(char a)" << endl;
}

//重载2: 方法名相同,参数个数不同
void func(int a, char b){
    cout << "func(int a, char b)" << endl;
}

//重载2:方法名相同,参数类型顺序不同
void func(char a, int b){
    cout << "func(int a, char b)" << endl;
}

//重载错误: 返回值不同不能构成重载
//error:Functions that differ only in their return type cannot be overloaded
//int func(char a, int b){
//    cout << "func(int a, char b)" << endl;
//}

int main(void){
    //1 测试函数重载规则
    func(10);
    func(10,'a');
    func('a', 10);
    return 0;
}

执行结果

func(int a)
func(int a, char b)
func(int a, char b)
4.2 重载底层实现
//1 底层实现对应的方法名为function_c
void method(char a){
    cout << "function(char a)" << endl;
}
//2 底层实现对应的方法名为function_ci
void method(char a, int b){
    cout << "function(char a, int b)" << endl;
}

int main(void){
    //2 重载底层实现 (void int short long double char) ---> visldc
    method('a');
    method('a', 10);
    return 0;
}

执行结果

function(char a)
function(char a, int b)
4.3 函数重载与函数默认参数
#include <iostream>
using namespace std;

void func(int a){
    cout << "func(int a)" << endl;
}

void func(int a, int b = 0){
    cout << "func(int a, int b = 0)" << endl;
}

int main(void){
    //1 存在二义性,编译不通过
    //func(10); //Error:Call to 'func' is ambiguous
    return 0;
}
4.4 函数重载和函数指针
#include <iostream>
using namespace std;

void func(int a, int b){
    cout << "a = " << a << ", b = "  << b << endl;
}

//声明一个函数类型,返回值为void, 参数列表为int, int
typedef void(functype)(int, int);

//声明一个函数指针类型,返回值为void, 参数列表为int, int
typedef void(*functype_pointer)(int, int);

int main(void){
    //1 定义一个函数指针方式1
    functype *fp1 = NULL;
    fp1 = func;
    fp1(10, 20);
    
    //2 定义一个函数指针方式2
    functype_pointer fp2 = NULL;
    fp2 = func;
    fp2(10, 20);
    
    //3 定义一个函数指针方式3
    void(*fp3)(int, int) = NULL;
    fp3 = func;
    fp3(10, 20);
    
    //4 定义一个函数指针方式4
    void(*fp4)(int, int) = func;
    fp4(10, 20);
    
    return 0;
}

执行结果

a = 10, b = 20
a = 10, b = 20
a = 10, b = 20
a = 10, b = 20
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值