进一步了解C++函数的各种参数以及重载,了解C++部分的内存模型,C++独特的引用方式,巧妙替换指针,初步了解类与对象。满满的知识,希望大家能多多支持

这篇具有很好参考价值的文章主要介绍了进一步了解C++函数的各种参数以及重载,了解C++部分的内存模型,C++独特的引用方式,巧妙替换指针,初步了解类与对象。满满的知识,希望大家能多多支持。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

进一步了解C++函数的各种参数以及重载,了解C++部分的内存模型,C++独特的引用方式,巧妙替换指针,初步了解类与对象。满满的知识,希望大家能多多支持

C++的编程精华,走过路过千万不要错过啊!废话少说,我们直接进入正题!!!!

函数高级

C++的函数提高

函数默认参数

在C++中,函数的形参列表中的形参是可以有默认值的。

语法返回值类型 函数名 (参数 = 默认值){}

示例

#include<iostream>
using namespace std;
​
//函数的默认参数
//如果我们自己传入数据,就用自己的数据,如果没有那就用默认值
//语法:返回值类型 函数名称(形参 = 默认值){}
int func(int a,int b = 20,int c = 30)
{
    return a + b + c;
}
​
//注意事项
//如果某个位置已经有了默认参数,那么这个位置从左往右都必须有默认值
//如果函数声明有了默认参数,函数实现就不能有默认值
//声明和实现只能有一个默认参数
int func2(int a = 10,int b = 20);
int func2(int a = 10,int b = 20)//error
{
    return a + b;
}
​
​
int main()
{
    cout << func(10) << endl;
    cout << func(30) << endl;
    return 0;
}

函数占位参数

C++中函数的形参列表里可以有占位参教,用来做占位,调用函数时必须填补该位置

语法返回值类型 函数名 (数据类型){}

在现阶段函数的占位参数存在意义不大,但是后面的课程中会用到该技术

示例

#include<iostream>
using namespace std;
//函数占位参数,占位参数也可以有默认参数
void func(int a,int )
{
    cout << "this is func" << endl;
}
​
int main()
{
    func(10,10);//占位参数必须填补
    return 0;
}

函数重载

作用:函数名可以相同,提高复用性

函数重载满足条件

  1. 同一个作用域下

  2. 函数名称相同

  3. 函数参数类型不同或者个数不同或者顺序不同

注意:函数的返回值不可以作为函数重载的条件

示例

#include<iostream>
using namespace std;
​
//函数重载
//可以让函数名相同,提高复用性
​
//函数重载满足条件
//1. 同一个作用域下
//2. 函数名称相同
//3. 函数参数类型不同或者个数不同或者顺序不同
void func()
{
    cout << "func函数的调用" << endl;
}
​
void func(int a)
{
    cout << "func(int a)函数的调用!" << endl;
}
​
void func(double a)
{
    cout << "func(double a)函数的调用!" << endl;
}
​
void func(int a, double b)
{
    cout << "func(int a, double b)函数的调用!" << endl;
}
​
void func(double a,int b)
{
    cout << "func(double a,int b)函数的调用!" << endl;
}
​
int main()
{
    func();
    func(1);
    func(3.14);
    func(1,3.14);
    func(3.14,1);
    return 0;
}
func函数的调用
func(int a)函数的调用!
func(double a)函数的调用!
func(int a, double b)函数的调用!
func(double a,int b)函数的调用!

注意

int func(double a,int b)//这个无法重载,函数重载不可以作为函数重载条件
{
    cout << "func(double a,int b)函数的调用!" << endl;
}

函数重载的注意事项

  1. 引用作为重载条件

  2. 函数重载碰到函数默认参数

示例

#include<iostream>
using namespace std;
//引用作为重载条件
void func(int &a)
{
    cout << "func(int &a)" << endl;
}
​
void func(const int &a)//const int &a = 10;这是合法的代码
{
    cout << "func(const int &a)" << endl;
}
//函数重载碰到默认参数
void func2(int a,int b = 10)
{
    cout << "func2(int a,int b)" << endl;
}
​
void func2(int a)
{
    cout << "func2(int a)" << endl;
}
​
int main()
{
    int a = 10;
    func(a);//实现的是func(int &a)的函数
    func(10);//实现的是fun(const int &a)的函数
    func2(10);//当函数重载碰到默认参数,就会出现二义性,error
    return 0;
}

内存模型

C++核心编程

主要针对C++面向对象编程技术做详细讲解,探讨C++中的核心和精髓。

内存分区模型

C++程序在执行时。将内存大方向划分为4个区域

  1. 代码区:存放函数体的二进制代码。由操作系统进行管理的。

  2. 全局区:存放全局变量和静态变量以及常量。

  3. 栈区:由编译器自动分配释放,存放函数的参数值局部变量等。

  4. 堆区:由程序员分配和释放,若程序员下释放,程序结束时由操作系统回收。

内存四区意义

不同区域存放的数据。暖予不同的生金周明,给我们更大的灵活编程

程序运行前

在程序编译后,生成了exe可执行程序,未执行该程序前分为两个区域 代码区:

  1. 存放CPU执行的机器指令

  2. 代码区是共享的,共享的目的是对于频繁被执行的程序,只需要在内存中有一份代码即可

  3. 代码区是只读的,使其只读的原因是防止程序意外地修改了它的指令

全局区:

  1. 全局变量和静态变量存放在此

  2. 全局区还包含了常量区,字符串常量和其他常量也存放在此

  3. 该区域的数据在程序结束后由操作系统释放

示例:

#include<iostream>
using namespace std;
//全局变量
int g_a = 10;
int g_b = 10;
//const修饰的全局变量
const int c_g_a = 10;
const int c_g_b = 10;
int main()
{
    //创建普通的局部变量
    int a = 10;
    int b = 10;
    cout << "局部变量a的地址为:" << (int*)&a << endl;
    cout << "局部变量b的地址为:" << (int*)&b << endl;
    
    cout << "全局变量g_a的地址为:" << (int*)&g_a << endl;
    cout << "全局变量g_b的地址为:" << (int*)&g_b << endl;
    
    //静态变量,在普通变量前面加static,属于静态变量
    static int s_a = 10;
    static int s_b = 10;
    cout << "静态变量s_a的地址为:" << (int*)&s_a <<endl;
    cout << "静态变量s_b的地址为:" << (int*)&s_b <<endl;
    
    //常量
    //字符串常量
    cout << "字符串常量的地址:" << (int*)&"hello" << endl;
    //const修饰常量
    cout << "全局常量 c_g_a的地址为:" << (int*)&c_g_a << endl;
    cout << "全局常量 c_g_b的地址为:" << (int*)&c_g_b << endl;
    //const修饰的局部变量
    const int c_l_a = 10;
    const int c_l_b = 10;
    cout << "局部变量 c_l_a的地址为:" << (int*)&c_l_a << endl;
    cout << "局部变量 c_l_b的地址为:" << (int*)&c_l_b << endl;
    return 0;
}
局部变量a的地址为:0x61fe1c
局部变量b的地址为:0x61fe18
全局变量g_a的地址为:0x403010
全局变量g_b的地址为:0x403014
静态变量s_a的地址为:0x403018
静态变量s_b的地址为:0x40301c
字符串常量的地址:0x40409f
全局常量 c_g_a的地址为:0x404004
全局常量 c_g_b的地址为:0x404008
局部变量 c_l_a的地址为:0x61fe14
局部变量 c_l_b的地址为:0x61fe10

总结:

  1. C++中在程序运行前分为全局区和代码区

  2. 代码区特点是共享和只读

  3. 全局区中存放全局变量、静志变量、常量

  4. 常量区中存放const修饰的全局常量和字符串常量

程序运行后

栈区:

  1. 由编译器自动分配程放存放函数的参数,局部变量等

  2. 注意事项:不要返回局部变量的地址,栈区开辟的数据由编译器自动释放

示例:

#include<iostream>
using namespace std;
//栈区数据注意事项,不要返回局部变量的地址
//栈区的数据由编译器管理开辟和释放
int* func(int b)//形参数据也会放在栈区
{
    b = 100;
    int a = 10;//局部变量 存放在栈区,栈区的数据在执行完后自动释放
    return &a;//返回局部变量的地址
}
int main()
{
    //接受func函数的返回值
    int* p = func();
    cout << *p << endl;//这里显示错误,error
    return 0;
}

堆区:

  1. 由程序员分配释放,若程序员不释放,程序结束时由操作系统回收

  2. 在C++中主要利用new在堆区开辟内存

示例:

#include<iostream>
using namespace std;
int* func()
{
    //利用new关键,可以将数据开辟到堆区
    //指针 本质是一个局部变量,放在栈上,但是数据放在堆区
    int *p = new int(10);
    return p;
}
​
int main()
{
    //堆区开辟数据
    int* a = func();
    cout << *a << endl;
    return 0;
}

总结: 堆区数据由程序员管理开辟和释放 堆区数据开辟利用new关键字进行开辟内存

new操作符

C++中利用new操作符在堆区开辟数据 堆区开辟的数据,由程序员手动开辟,手动释放。 释放利用操作符delete 语法:new 数据类型 利用new创建的数据,返回该数据对应的类型的指针

示例:

#include<iostream>
using namespace std;
//new的基本语法
int * func()
{
    //在堆区创建整型数据
    //返回该数据类型的指针
    int * p = new int(10);
    return p;
}
​
void test01()
{
    int * p = func();
    cout << *p << endl;
    //堆区的数据由程序员管理开辟,程序员管理释放
    //如果想释放堆区数据,
    delete p;
    cout << *p << endl;//非法访问,数据已释放,error,会出现乱码
}
​
//在堆区利用new开辟数据
void test02()
{
    //创建10个整型数据的数组在堆区
    int * arr = new int[10];//代表数组有10个元素
    for(int i = 0;i < 10; i++)
    {
        arr[i] = i + 100;
    }
    for(int i = 0;i < 10; i++)
    {
        cout << arr[i] << " ";
    }
    cout << endl;
    //释放堆区数组
    //释放数组的时候,要加[]才可以
    delete[] arr;
}
int main()
{
    test01();
    test02();
    return 0;
}

引用

引用C++核心编程引用的基本使用引用注意事项引用做函数参数引用函数返回值引用的本质常量引用

C++核心编程

引用的基本使用

作用:给变量起名

语法数据类型 &别名 = 原名

示例

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

引用注意事项

  1. 引用必须初始化

  2. 引用在初始化后,不可以改变

示例

#inlcude<iostream>
using namespace std;
int main()
{
    //引用必须初始化
    int a = 10;
    int &b;//error
    int &b = a;
    
    //引用初始化后,是不能更改引用的
    int c = 20;
    b = c;//error
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
    cout << "c = " << c << endl;
    return 0;
}

引用做函数参数

作用:函数传参时,可以利用引用的技术让形参修饰实参

优点:可以简化指针修改实参

示例

#include<iostream>
using namespace std;
//交换函数
//值传递
void mySwap01(int a,int b)
{
    int tmp = a;
    a = b;
    b = tmp;
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;//只在这个函数里面才有效,结束后还给系统
}
​
//指针的地址传递
void mySwap02(int* a,int* b)
{
    int tmp = *a;
    *a = *b;
    *b = tmp;
}
​
//引用传递
void mySwap03(int &a,int &b)
{
    int tmp = a;
    a = b;
    b = tmp;
}
​
int main()
{
    int a = 10;
    int b = 20;
    mySwap01(a,b);
    mySwap02(&a,&b);
    mySwap03(a,b);//引用传递,形参会修饰实参的
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
    return 0;
}

引用函数返回值

作用:引用是可以作为函数的返回值存在的

注意:不要返回局部变量引用

用法:函数调用作为左值

示例

#include<iostream>
using namespace std;
​
//不要返回局部变量的引用
int& test01()
{
    int a = 10;//局部变量存放在四区中的栈区
    return a;
}
​
//函数的调用可以作为左值
int& test02()
{
    static int a = 10;//静态变量存放在全局区,在程序结束后由系统回收
    return a;
}
​
int main()
{
    int &ref = test01();
    cout << ref << endl;//error,a的内存已经释放,属于非法访问
    int &ret = test02();
    cout << ret <<endl;
    test02() = 1000;
    cout << ret <<endl;//这里的值ret会改成1000
    return 0;
}
引用的本质

本质:引用的本质在C++内部实现是一个指针常量。

示例

#include<iostream>
using namespace std;
​
//发现是引用,转化为int* const ref = &a;
void func(int& ref)
{
    ref = 100;//ref是引用,转换为*ref = 100;
}
​
int main()
{
    int a = 10;
    
    //自动转换为int* const ref = &a;指针常量是指针指向不可改,也说明了为何引用不可更改
    int& ref = a;
    ref = 20;//内部发现ref是引用,自动帮我们转化为*ref = 20;
    
    cout << "a = " << a << endl;
    cout << "ref = " << ref << endl;
    
    func(a);
    return 0;
}

常量引用

作用:常量引用主要用来修饰形微,防止误操作

在函数形参列表中,可以加const修饰形参,防止形参改变实参

#include<iostream>
using namespace std;
​
void showValue(const int & ref)
{
    ref = 20;//error,无法改变
}
int main()
{
    //常量引用
    //使用场景:用来修饰形参,防止误操作
    int a = 10;
    //int & ref = 10;error 引用必须引用一块合法的内存空间
    const int & ref =10;//这是允许的,编译器将代码修改为 int temp = 10; const int & ref = temp;
    
    int b = 100;
    showValue(b);
    cout << b << endl;
    return 0;
}

类与对象

C++中类与对象的学习

C++面向对象的三大特性为:封装继承多态

C++认为万事万物皆为对象。对象上有其属性和行为

例如: 人可以作为对象,属性有姓名、年龄、身高、体重…… 行为有走、跑、跳、吃饭、唱歌……

车也可以作为对象,属性有轮胎、方向盘、车灯……行为有载人、放音乐、开启空调……

具有相同性质的对象,我们可以抽象称为,人属于人类,车属于车类

封装

封装的意义1

封装是C++面向对象的三大特性之一

封装的意义:

  1. 将属性和行为作为一个整体

  2. 将属性和行为加以权限控制

封装意义1:

在设计类的时候,属性和行为写在一起,表现事物

语法class 类名 { 访问权限: 属性 / 行为 };

设计一个圆类

求圆的周长

#include<iostream>
using namespace std;
​
const double PI = 3.14;
//设计一个圆类,求圆的周长
//圆求周长的公式:2 * PI * 半径
//class代表设计一个类,类后面紧跟着的就是类名称
class Circle
{
    //访问权限
    //公共权限
    public:
    
    //属性
    //半径
    int m_r;
    
    //行为
    //获取圆的周长
    double calculateZC()
    {
        return 2 * PI * m_r;
    }
    
};
​
int main()
{
    //通过圆类 创建一个具体的圆(对象)
    //实例化 (通过一个类 创建一个对象的过程)
    Circle c1;
    //对圆对象的属性进行赋值
    c1.m_r = 10;
    cout << "圆的周长" << c1.calculateZC() << endl;
    return 0;
}

设计一个学生类

属性有姓名学号,可以给姓名学号赋值,可以显示学生姓名和学号

#include<iostream>
#include<string>
using namespace std;
​
class Student
{
public:
    string m_Name;
    int m_Id;
    void showStudent()
    {
        cout << "姓名:" << m_Name << "\t" << "学号:" << m_Id << endl; 
    }
};
​
int main()
{
    //实例化对象
    Student s1;
    //s1对象进行属性赋值操作
    s1.m_Name = "zhangsan";
    s1.m_Id = 12345;
    s1.showStudent();
    
    //实例化对象
    Student s2;
    //s1对象进行属性赋值操作
    s2.m_Name = "lisi";
    s2.m_Id = 12346;
    s2.showStudent();
    return 0;
}

亦可以用下面的方式对类进行赋值操作

#include<iostream>
#include<string>
using namespace std;
​
class Student
{
public:
    //类中的属性和行为统一称为成员
    string m_Name;
    int m_Id;
public:
    void showStudent()
    {
        cout << "姓名:" << m_Name << "\t" << "学号:" << m_Id << endl; 
    }
    void setName(string name)
    {
        m_Name = name;
    }
    void setId(int id)
    {
        m_Id = id;
    }
};
​
int main()
{
    //实例化对象
    Student s1;
    //s1对象进行属性赋值操作
    s1.setName("zhangsan");
    s1.setId(12345);
    s1.showStudent();
    return 0;
}

封装的意义2

类在设计时,可以吧属性和行为放在不同的权限下,加以控制

访问权限有三种:

  1. public 公共权限

  2. protected 保护权限

  3. private 私有权限

示例

#include<iostream>
#include<string>
using namespace std;
//访问权限
//公共权限public    成员类内可以访问    类外也可以访问
//保护权限protected 成员类内可以访问    类外不可以访问
//私有权限private   成员类内可以访问    类外不可以访问
class Person
{
public:
    //公共权限
    string m_Name;
protected:
    //保护权限
    string m_Car;
private:
    //私有权限
    int m_Password;
public:
    void func()
    {
        m_Name = "zhangsan";
        m_Car = "Tractor";
        m_Password = 123456;
    }
    void func2()
    {
        cout << "1." << m_Name << "\t" << "2." << m_Car << "\t" << "3." << m_Password << endl;
    }
};
​
int main()
{
    //实例化具体对象
    Person p1;
    //p1.m_Car = "Benz";//error,保护权限内容在类外是访问不到的
    //p1.m_Password = 123;error,保护权限内容在类外是访问不到的
    p1.func();
    p1.m_Name = "Lisi";
    p1.func2();
    return 0;
}

struct和class的区别

在C++中struct和class唯一的区别就在于默认的访问权限不同 区别:

  1. struct 默认权限为公共

  2. class 默认权限为私有

#include<iostream>
using namespace std;
​
class C1
{
    int m_A;//默认权限是私有权限
};
​
struct C2
{
    int m_A;//默认权限是公共权限
};
​
int main()
{
    C1 c1;
    c1.m_A = 10;//error
    struct C2 c2;
    c2.m_A = 10;//正确的
    return 0;
}

成员属性设置为私有

优点1:将所有成员属性设置为私有,可以自己控制读写权限

优点2:对于写权限,我们可以检测数据的有效性

示例

#include<iostream>
#include<string>
//成员属性设置为私有
//可以自己控制读写权限
//对于写权限可以检测数据的有效性
using namespace std;
int main()
{
    return 0;
}

进一步了解C++函数的各种参数以及重载,了解C++部分的内存模型,C++独特的引用方式,巧妙替换指针,初步了解类与对象。满满的知识,希望大家能多多支持文章来源地址https://www.toymoban.com/news/detail-416715.html

到了这里,关于进一步了解C++函数的各种参数以及重载,了解C++部分的内存模型,C++独特的引用方式,巧妙替换指针,初步了解类与对象。满满的知识,希望大家能多多支持的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • YOLOv8 独家改进最新PWConv核心结构|来自CVPR2023,可以直接写模型改进,进一步轻量化!测试数据集mAP有效涨点,进一步降低参数量,追求更高的 FLOPS

    💡 本篇内容 :YOLOv8 独家原创改进最新PWConv核心结构|来自最新CVPR2023顶会, 🚀🚀各种数据集mAP有效涨点,进一步降低参数量,追求更高的 FLOPS 💡 🚀🚀🚀内含·改进源代码·,按步骤操作运行改进后的代码即可 重点 :🔥🔥🔥有同学已经使用这个 PWConv 创新点 在 数据集

    2024年02月08日
    浏览(29)
  • YOLOv5、YOLOv7改进首发最新PWConv核心结构|来自最新CVPR2023顶会,进一步轻量化!测试数据集mAP有效涨点,进一步降低参数量,追求更高的 FLOPS

    💡 本篇内容 :YOLOv5,YOLOv7改进首发最新PWConv核心结构|来自最新顶会CVPR2023, 🚀🚀各种数据集mAP有效涨点,进一步降低参数量,追求更高的 FLOPS 💡 🚀🚀🚀内含·改进源代码·,按步骤操作运行改进后的代码即可 重点 :🔥🔥🔥有同学已经使用这个 PWConv 创新点 在 数据集

    2024年02月06日
    浏览(35)
  • 从零开始实现C++ TinyWebServer(七)---- 进一步优化服务器,剑指定时器小根堆

    昨天晚上失眠了,到2点估计才睡着,我想这估计和下午那杯咖啡没消化完和我看巅峰说唱看到0:40有关系吧(太兴奋了)导致我今天早上9点半才出寝室,做了几个算法题,一上午就过去了。 我已经基本习惯把前言部分当成我的free talk部分了,每次开启一篇新的篇章的时候,就

    2024年02月10日
    浏览(32)
  • Opencv中goodFeaturesToTrack函数(Harris角点、Shi-Tomasi角点检测)算子速度的进一步优化(1920*1080测试图11ms处理完成)。

    搜索到某个效果很好的视频去燥的算法,感觉效果比较牛逼,就是速度比较慢,如果能做到实时,那还是很有实用价值的。于是盲目的选择了这个课题,遇到的第一个函数就是角点检测,大概六七年用过C#实现过Harris角点以及SUSAN角点。因此相关的理论还是有所了解的,不过那

    2024年02月06日
    浏览(32)
  • 进一步探讨二分

    接下来简单探讨几种查询 严格大于等于x的情况,只需要 去掉等号号 即可 严格小于x的情况,将 小于符号改为大于符号 即可 严格小于等于x的情况,也只需要 去掉等号 即可 写题过程中还有具体的探讨,可以从这几种方法中迁移应用

    2024年02月16日
    浏览(32)
  • 【Vue路由(router)进一步详解】

    本篇文章主要针对已经掌握Vue路由(router)基础以及路由嵌套的用户群体,如果你是Vue路由初学者的话,不仿先去看看 【Vue路由(router)的基本使用】这篇文章 接上一篇文章理解Vue路由中常用的知识点 在实际开发过程中,我们可能不单单要实现简单的页面跳转动作,可能在

    2023年04月08日
    浏览(32)
  • Unity的GPUSkinning进一步介绍

      大家好,我是阿赵。   在几年前,我曾经写过一篇介绍GPUSkinning的文章,这么多年之后,还是看到不停有朋友在翻看这篇旧文章。今天上去GitHub看了一下,GPUSkinning这个开源的插件已经很久没有更新过了,还是停留在2017年的0.2.3版本。GPUSkinning的魅力在于可以在消耗比较

    2024年02月05日
    浏览(36)
  • Druid未授权漏洞进一步的利用

    Druid是阿里巴巴数据库出品的为监控而生的数据库连接池。并且Druid提供的监控功能包括监控SQL的执行时间、监控Web URI的请求、Session监控等。Druid本身是不存在什么漏洞的,但当开发者配置不当时就可能造成未授权访问。本文除了介绍Druid未授权漏洞之外,还要讲的是一种该漏

    2024年02月11日
    浏览(34)
  • 数据结构--并查集的进一步优化

    压缩路径 − − F i n d 操作,先找到根节点,再将查找路径上所有结点都挂到根结点下 color{red}压缩路径 -- Find操作,先找到根节点,再将查找路径上所有结点都挂到根结点下 压缩路径 − − F in d 操作,先找到根节点,再将查找路径上所有结点都挂到根结点下 每次Find操作,

    2024年02月15日
    浏览(40)
  • [架构之路-203] - 对系统需求类型的进一步澄清

    目录 业务/商业需求: 用户/客户需求: 功能性需求: 非功能性需求: 系统需求: 约束条件: 软件需求说明书: 软件质量: 是自顶向下的需求,往往来自于中高层管理人员(或监管、政策要求),基于业务运营管理的直接诉求和要求。需要使用商业/工作语言描述业务/商业

    2024年02月07日
    浏览(54)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包