深圳高端网站案例wordpress中文字体
news/
2025/9/24 0:12:44/
文章来源:
深圳高端网站案例,wordpress中文字体,福田欧曼官方网站,做外贸生意在哪个网站目录
C中的函数重载
函数重载介绍
函数类型的使用
C中的引用
引用的介绍
引用的使用
引用与指针的对比
常量引用
引用在实际中的使用
函数返回值
返回值和返回引用时间消耗对比
函数形式参数
形式参数为值与形式参数为引用时间消耗对比
内联函数
内联函数的特点…目录
C中的函数重载
函数重载介绍
函数类型的使用
C中的引用
引用的介绍
引用的使用
引用与指针的对比
常量引用
引用在实际中的使用
函数返回值
返回值和返回引用时间消耗对比
函数形式参数
形式参数为值与形式参数为引用时间消耗对比
内联函数
内联函数的特点 C中的函数重载
函数重载介绍
在C语言中不能出现名字相同的函数因为C语言中的编译过程函数是通过函数名以及对应的地址来找到函数并调用的如果名字相同那么编译器将无法分辨是哪一个函数
在C中允许在同一作用域下使用相同的函数名配合参数不同、参数类型和不同参数类型的不同顺序构成函数重载
//参数类型不同的重载
//整型参数
int add(int a, int b)
{return a b;
}
//浮点型参数
double add(double a, double b)
{return a b;
}//参数个数不同的重载
//两个参数
int add(int a, int b)
{return a b;
}
//三个参数
int add(int a, int b, int c)
{return a b c;
}//不同类型的但数量相同情况下的不同参数顺序的重载
//注意变量名不需要更改顺序
//int类型在前char类型在后
int getcharacter(int a, char b)
{return b;
}
//char类型在前int类型在后
int getcharacter(char a, int b)
{return a;
} 注意返回类型不可以作为判断函数是否重载的条件函数重载只有三种特点
参数个数不同参数类型不同相同个数相互类型不同情况下不同的参数顺序
函数重载一般用于针对不同类型实现相同的功能例如
//函数重载
//针对整型的加法函数
int add(int a, int b)
{return a b;
}//针对浮点型的加法函数
double add(double a, double b)
{return a b;
}
函数类型的使用
在没有进入类之前对于全局域的函数重载来说正常调用对应函数名但是需要传递正确的实参例如
//整型加法
int add(int a, int b)
{return a b;
}
//浮点型加法
double add(double a, double b)
{return a b;
}
#include iostream
using namespace std;int main()
{ //传哪种类型值就调用哪种类型的函数cout 整型加法 add(1, 2) endl;cout 浮点型加法 add(1.1, 2.2) endl;return 0;
}
输出结果
整型加法3
浮点型加法3.3
如果使用命名空间则需要满足需要重载的函数在同一个命名空间并且使用域作用限定符调用函数传递实参时依旧是满足传哪种类型的值就调用哪种类型的函数
注意含有缺省参数的函数和无缺省参数的函数无法构成函数重载例如
//缺省参数与函数重载
int add(int a 10, int b 20)
{return a b;
}int add(int a, int b 30)
{return a b;
}
//将会报错为add函数重定义 了解
C是通过函数名修饰规则来区分只要参数不同修饰出来的名字就不一样就支持了重载
例如在Linux平台下用g编译的函数重载后的函数名为_Z3addii对应两个int类型参数的add函数_Z3adddd对应两个double类型参数的add函数两个函数名中的3为函数本身不包括类型的名字长度例如add函数名字是3个字符的长度
C中的引用
引用的介绍
在C语言中为了可以通过其他变量直接改变某一个变量的值由此引出了指针的概念通过指针类型可以改变该指针指向的空间的内容
在C中使用引用来辅助指针的使用例如 注意引用的底层依旧是指针实现
//指针中的swap函数
void swap(int* num1, int* num2)
{int tmp *num1;*num1 *num2;*num2 tmp;
}//使用引用的函数
void swap(int num1, int num2)
{int tmp num1;num1 num2;num2 tmp;
}#include iostream
using namespace std;int main()
{//C语言中的swap函数int a 1;int b 0;cout 指针交换 endl;cout 交换前 endl;cout a b endl;swap(a, b);cout 交换后 endl;cout a b endl;//C中使用引用的swap函数a 1;b 0;cout endl;cout 引用交换 endl;cout 交换前 endl;cout a b endl;swap(a, b);cout 交换后 endl;cout a b endl;return 0;
}
输出结果
指针交换
交换前
1 0
交换后
0 1引用交换
交换前
1 0
交换后
0 1
在C中引用相当于为变量取一个别名引用变量这个别名和其对应的变量引用实体共用一个地址所以可以通过引用直接改变对应的变量所在空间的内容
所以在上面的代码中对于引用变量的函数void swap(int num1, int num2)num1和num2为实参a和b的别名所以此时num1和num2与a和b的地址相同直接在swap函数改变num1和num2的值即可改变实参a和b中的值
引用的使用
在C中使用下面的语法创建引用变量
引用实体的类型 引用变量名 引用实体; 此处的引用实体可以是任何类型包括指针类型以及引用类型
//引用与指针
#include iostream
using namespace std;int main()
{int a 0;//指针类型int* p a;cout 指针修改前 endl;cout a endl;*p 1;cout 修改后 endl;cout a endl;//引用类型a 0;int rp a;cout 引用修改前 endl;cout a endl;rp 1;cout 修改后 endl;cout a endl;//引用实体为指针类型a 0;int* rpp p;cout 引用类型为指针修改前 endl;cout a endl;*rpp 1;cout 修改后 endl;cout a endl;//引用变量作为引用实体a 0;int r rp;cout 引用类型为引用变量修改前 endl;cout a endl;rp 1;cout 修改后 endl;cout a endl;return 0;
}
输出结果
指针修改前
0
修改后
1
引用修改前
0
修改后
1
引用类型为指针修改前
0
修改后
1
引用类型为引用变量修改前
0
修改后
1
引用与指针的对比
在C中引用有以下的特点
引用在定义时必须初始化一个变量可以有多个引用引用一旦引用一个实体就不能再引用其他实体即不可以更改实体没有NULL引用使用sizeof关键字计算某个引用的大小时计算的是引用实体的类型大小而不是一个固定值引用变量自加1相当于对应实体内容加1引用没有多级引用即没有二级及以上引用引用在访问指向的实体时不需要解引用由编译器处理除非实体是指针类型引用在概念上没有实际地址
对比指针的特点
指针在使用之前可以不初始化但是在VS上面必须初始化一个变量可以有多个指针一个指针指向一个变量时可以改变其指向使其指向下一个变量有NULL指针使用sizeof关键字计算某个指针的大小时计算的是指针变量的大小是一个固定值在32位机上值为4在64位机上是8指针变量自加1相当于跳过指向的类型占用的内存大小个字节指针存在二级及以上的引用指针不论指向的类型如何都必须显式解引用指针在概念上和实际上都有自己的实际地址
//指针可以更改指向引用不可以
#include iostream
using namespace std;int main()
{int a 0;//两个引用指向同一个变量a//变量a给引用变量bint b a;cout 初始a中的值 a endl;//通过引用b改变a的值b 20;cout 通过引用改变a中的值 a endl;//改变引用a实体的引用变量b使其指向ccout 初始a中的值 a endl;int c 10;cout 初始c中的值 c endl;b c;cout 现在a中的值 a endl;//通过引用b改变c的值b 30;cout 当前c中的值 c endl;cout 当前a中的值 a endl;return 0;
}
输出结果
初始a中的值0
通过引用改变a中的值20
初始a中的值20
初始c中的值10
现在a中的值10
当前c中的值10
当前a中的值30
//从上面的结果中可以看到尽管b引用显式得改变了指向使其指向c但是实际上只是将c中的值给了b引用而因为引用b的指向不可以改变故依旧改变的是a中的值//sizeof
#include iostream
using namespace std;int main()
{//一个变量可以有多个引用和指针int a 0;//两个引用指向同一个变量aint r a;//两个指针指向同一个变量aint* p a;int* r2 p;cout 计算引用变量大小(引用int类型) sizeof(r) endl;cout 计算引用变量大小(引用int*类型) sizeof(r2) endl;cout 计算引用指针大小(64位机指向int类型) sizeof(p) endl;return 0;
}
输出结果
计算引用变量大小(引用int类型)4
计算引用变量大小(引用int*类型)8
计算引用指针大小(64位机指向int类型)8//引用变量和指针1操作
#include iostream
using namespace std;int main()
{int arr[4] { 1,2,3,4 };int a1 arr[0];int* a2 arr[0];//const int* a4 arr[0];//无法初始化cout 计算引用实体类型为int类型1跳过的大小 endl;cout 开始位置 arr[0] 对应数值 arr[0] endl;cout 结束位置对应数值 a1 1 endl;cout 计算指针1跳过的大小 endl;cout 开始位置 arr[0] 对应数值 arr[0] endl;cout 结束位置 a2 1 endl;cout 计算引用实体类型为int*类型1跳过的大小 endl;a2 arr;int* a3 a2;const int* a4 arr[0];//注意不可以使用这种写法因为当前编译器不知道到底右侧值是否可以修改cout 开始位置 arr[0] 对应数值 arr[0] endl;cout 结束位置 a3 1 endl;return 0;
}
输出结果
计算引用实体类型为int类型1跳过的大小
开始位置000000970C4FF7B8 对应数值1
结束位置对应数值2
计算指针1跳过的大小
开始位置000000970C4FF7B8 对应数值1
结束位置000000970C4FF7BC
计算引用实体类型为int*类型1跳过的大小
开始位置000000970C4FF7B8 对应数值1
结束位置000000970C4FF7BC//引用本身的地址和指针本身的地址
#include iostream
using namespace std;int main()
{//一个变量可以有多个引用和指针int a 0;//两个引用指向同一个变量aint r a;//两个指针指向同一个变量aint* p a;int* r2 p;cout 引用实体为int类型变量的地址 r endl;cout 引用实体为int*类型变量的地址 r2 endl;cout 指针变量指向的int类型变量的地址 p endl;cout 指针变量自身的地址 p endl;return 0;
}
输出结果
引用实体为int类型变量的地址0000000C97EFF5A4
引用实体为int*类型变量的地址0000000C97EFF608
指针变量指向的int类型变量的地址0000000C97EFF5A4
指针变量自身的地址0000000C97EFF608
常量引用
在C语言中可以使用const指针修饰指针变量并且const可以修饰指针变量整体使得无法通过解引用该指针修改指向空间的内容也可以放在变量名前方限制指针无法指向其他对象
在C中也存在const修饰的引用但是const只能放在引用变量整体的前面即const int a例如 在指针/引用中指针和引用的权限只可以缩小不可以放大
//常量引用
#include iostream
using namespace std;int main()
{//对于常量来说需要使用常量引用变量才能引用常量实体const int a 0;const int a1 a;const int a2 10;//10为常量值double d 2.34;//int a3 d;//无法编译但不是类型不同的原因const int a3 d;//可以编译//const int* p d;//但是指针无法做到同样的实现原因是类型不同return 0;
} 在强制类型转换的过程中实际上是创建了一个临时变量例如
double b 2.34;
int a (int)b;
在此处的强制转换过程中a被赋值为强制转换为int类型的b但是b本身的值并没有改变b中存储的值依旧是2.34但是a中存的值为2所以强制转换过程中不会直接对需要强制转换的对象b进行改变而是取出该变量b中的数据放到临时变量中并转换为对应类型再给目标对象a
此时可以解释为什么上面的引用需要加const才可以编译通过
在上面的代码中d为double类型的变量而需要强制转换为int类型的变量给int类型的引用但是在强制转换过程中是先创建了临时变量存储的d中的值而临时变量中的值为常量值不可以被改变所以需要给int类型的引用加const才可以成功编译
引用在实际中的使用
函数返回值
//返回值
int add(int a, int b)
{static int z a b;return z;
}#include iostream
using namespace std;int main()
{int ret add(1, 2);cout ret endl;return 0;
}
输出结果
3//返回引用
int add(int a, int b)
{static int z a b;return z;
}#include iostream
using namespace std;int main()
{int ret add(1, 2);cout ret endl;return 0;
}
输出结果
3
在上面的代码中add函数中有一个static类型的变量直接返回值时需要将该变量的值存入寄存器中再由寄存器带回给add函数被ret接收而使用引用返回该类型的变量可以在一定程度上减少前面的步骤消耗
但是注意下面的代码可能会出现问题
#include iostream
using namespace std;int add(int a, int b)
{int z a b;return z;
}int main()
{int ret add(1, 2);//int ret add(1, 2);//依旧会有问题cout ret endl;cout 输出结果 ret endl;return 0;
}
输出结果
3
输出结果-858993460
//编译器警告返回局部变量或临时变量的地址: z
因为z是add函数中的局部变量出了add函数将会被销毁此时返回z是返回变量z的引用被ret接收后ret指向z的位置当z销毁后ret依旧指向该位置但是该位置的值已经不一定是刚才计算出来的结果因为add函数栈帧空间可能会被覆盖没被覆盖时该地址的值依旧是计算出来的值否则就是随机值具体取决于编译器如何分配空间 在使用引用作为函数返回值时注意引用的实体尽量不是临时变量或者局部变量除非返回作为形式参数的引用变量
所以如果函数返回时出了函数作用域如果返回对象还在(还没还给系统)则可以使用引用返回如果已经还给系统了则必须使用传值返回
返回值和返回引用时间消耗对比
#include iostream
using namespace std;#include time.h
struct A { int a[10000]; };
A a;
// 值返回
A TestFunc1() { return a; }
// 引用返回
A TestFunc2() { return a; }
void TestReturnByRefOrValue()
{// 以值作为函数的返回值类型size_t begin1 clock();for (size_t i 0; i 100000; i)TestFunc1();size_t end1 clock();// 以引用作为函数的返回值类型size_t begin2 clock();for (size_t i 0; i 100000; i)TestFunc2();size_t end2 clock();// 计算两个函数运算完成之后的时间cout TestFunc1 time: end1 - begin1 endl;cout TestFunc2 time: end2 - begin2 endl;
}int main()
{TestReturnByRefOrValue();return 0;
}
输出结果
TestFunc1 time:161
TestFunc2 time:1
函数形式参数
#include iostream
using namespace std;void swap(int num1, int num2)
{int tmp num1;num1 num2;num2 tmp;
}int main()
{int a 1;int b 0;cout 交换前的a和b a a b b endl;swap(a, b);cout 交换后的a和b a a b b endl;return 0;
}
输出结果
交换前的a和ba 1 b 0
交换后的a和ba 0 b 1
形式参数为值与形式参数为引用时间消耗对比
#include iostream
using namespace std;
#include time.h
struct A { int a[10000]; };
void TestFunc1(A a) {}
void TestFunc2(A a) {}
void TestRefAndValue()
{A a;// 以值作为函数参数size_t begin1 clock();for (size_t i 0; i 10000; i)TestFunc1(a);size_t end1 clock();// 以引用作为函数参数size_t begin2 clock();for (size_t i 0; i 10000; i)TestFunc2(a);size_t end2 clock();// 分别计算两个函数运行结束后的时间cout TestFunc1(A)-time: end1 - begin1 endl;cout TestFunc2(A)-time: end2 - begin2 endl;
}int main()
{TestRefAndValue();return 0;
}
输出结果
TestFunc1(A)-time:15
TestFunc2(A)-time:0
内联函数
在C语言中常量和宏函数一般用#define来定义优点是增强代码的复用性以及提高性能但是#define定义的二者在预处理时将会替换其在函数出现的位置从而导致下面的三个重要的问题
#define定义的宏函数和常量无法被调试代码可读性差可维护性差并且容易误用#define定义的宏函数没有类型的检查
在C中为了避免上述问题经常使用const和enum来表示常量而使用内联函数代替#define定义的宏函数
所谓内联函数即当函数代码量较小时在汇编代码中直接将函数代码替换掉原来的call函数名指令减少函数栈帧开辟时的开销从而实现直接执行函数但是缺点也就比较明显如果代码量太大将会导致替换后的函数指令很多为此C中的内联函数到底是真正的函数还是类似于C语言的宏函数取决于函数代码规模的大小如果函数代码量大那么尽管定义为内联函数还是会被编译器认作普通函数
在C中使用inline关键字修饰定义的函数语法如下
inline 普通函数定义
代码实例
//C语言中#define定义的ADD宏函数
#define ADD(x, y) ((x) (y))//C中内联函数
inline int add(int a, int b)
{return a b;
} 不建议将内联函数的声明和定义分开写二者分离会导致链接错误。因为inline会展开函数导致函数失去本身的地址声明的函数就无法被找到
//函数声明
inline int add(int a, int b);//函数定义
int add(int a, int b)
{return a b;
}
//编译报错为链接错误
内联函数的特点
inline是一种以存储空间不是内存空间换时间的做法如果编译器将函数当成内联函数处理在编译阶段会用函数体替换函数调用缺陷可能会使目标文件变大因为函数展开之后汇编代码量增多优势少了调用开销提高程序运行效率
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/914326.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!