【C++】引用、内联函数、函数重载、函数默认参数(缺省参数)与占位参数、extern “C“ 浅析
端午继续~
C++对C的扩展
目录
引用
普通变量名引用
对数组的引用
对指针的引用
对函数的引用
引用作为函数的参数
引用作为函数的返回类型
常引用
内联函数
函数重载
函数的默认参数(缺省参数)
默认参数和函数重载的二义性
占位参数
extern "C" 浅析
引用
本质:给变量名取别名,可以通过别名间接操作变量
&:引用说明符(不是取地址符)
给哪个变量取别名,就定义该变量
普通变量名引用
void Test()
{int a = 0;//给变量a取一个别名叫b //&修饰变量为别名,b就是a的别名 --- 引用int& b = a;//必须初始化,这里&不是取地址,是引用
}
注意:系统并不会为引用开辟空间,a,b代表同一个空间。
我们可以看一下地址
void Test()
{int a = 0;//给变量a取一个别名叫b //&修饰变量为别名,b就是a的别名 --- 引用int& b = a;//必须初始化cout << "&a = " << &a << endl;cout << "&b = " << &b << endl;
}
运行结果:
操作b等价于操作a
b = 10; 等价于操作了 a = 10;
对数组的引用
void Test_2()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int sz = sizeof(arr) / sizeof(arr[0]);//给数组arr取别名my_arr//注意这里要将&my_arr用括号括起来,否则my_arr会先于[10]结合int (&my_arr)[10] = arr;//访问的方式是一样int i = 0;for (i = 0; i < sz; i++){cout << my_arr[i] << " ";}
}
对指针的引用
void Test_3()
{int num = 6;int* p = #//给num取别名为 my_num int*& my_num = p;//这里&的优先级高于*,所以可以不用带括号//访问时,与指针的访问方法是一样的cout << "num = " << *my_num << endl;
}
对函数的引用
int main()
{//对函数Test_3取别名为My_Test_3void(&My_Test_3)() = Test_3;//注意括号不可省略//访问My_Test_3();return 0;
}
这么多例子,我们为什么要用引用,引用能解决什么问题?
咱往下走~
引用作为函数的参数
这是引用解决的主要问题,函数可以通过引用来操作外部变量
这里学过C语言的小伙伴可能注意到了,引用和指针十分相似
确实如此~
指针有一些操作比较麻烦地方:
形参是带指针*,并且实参要取地址,相对于来说比较麻烦。
所以在之后的学习中需要用到指针的地方尽量换成用引用
我们来对比一下,指针操作和引用操作,交换两个变量:
void My_exchange_1(int* x, int* y)
{int tmp = *x;*x = *y;*y = tmp;
}
void My_exchange_2(int& x, int& y)
{int tmp = x;x = y;y = tmp;
}
int main()
{int a = 6;int b = 8;cout << "交换前:a = " << a << " b = " << b << endl;My_exchange_1(&a, &b);//指针My_exchange_2(a, b);//引用cout << "交换后:a = " << a << " b = " << b << endl;return 0;
}
引用作为函数的返回类型
int& Ret()
{int num = 5;return num;
}
int main()
{int& b = Ret();//由于函数返回类型为int&,所以应该用别名类型来接收//这里相当于间接给num取了一个别名breturn 0;
}
但是,我们都知道,局部变量一旦出了函数,就销毁了,所以这里的相当于你给一个已经释放了的空间取别名,这是不因该的,(会出现段错误)所以函数返回时不应该返回局部变量 !
常引用
简而言之就是给常量取别名
注:不能通过常引用修改内容
可以看到这里编译器会报错,为什么呢?
给10这个常量取别名为num,10是一个常量,但num是一个变量, C++格式要求十分严格,所以这里会报错。
如何解决呢?
const修饰以下即可
有什么用呢?
防止函数内部修改外部的值
观察以下代码:
void Print(const int& x)
{//x = 100 //errcout << "num = " << x << endl;
}
int main()
{int num = 10;Print(num);return 0;
}
我们知道,用引用作为形参可以节省空间,x 和 num 表示一个空间,这里写一个函数,功能就是遍历,但同时我希望他的功能只是遍历,如果一不小心修改了形参 x,也意味着 num 被修改,很危险,所以这里可以用常引用修饰 x,使 x 不可被修改,既提高了安全性,有节省了空间。
内联函数
必须在定义函数的时候使用inline关键字修饰,声明时不需要
string Print();int main()
{cout << Print() << endl;return 0;
}inline string Print()
{string s1 = "端午节";string s2 = "快乐";return s1+s2;
}
直观感受是不是和普通函数差不多?
其实有很大滴作用!
内联函数:在编译阶段,将内联函数中的函数体 替换 函数调用处 ,避免函数调用时的开销(类似于宏函数,内联函数只是编译阶段直接替换,宏函数在预处理阶段替换)。
注意事项:
1.不能存在任何形式的循环语句
2.不能存在过多的判断语句
3.函数体不能过于庞大
4.不能对函数取地址
所以,加上inline并不是使函数成为内联函数的充要条件,他只是必要条件
加上inline只是告诉编译器,希望使其成为内联函数,最终是不是,还是有编译器决定。
函数重载
表示同一个函数在不同的场景下可以有不同的含义
同一个作用域,函数的参数类型,个数,顺序不同都可以重载(返回类型不能作为重载的条件)。
void print_1(int a)
{cout << "int" << endl;
}
void print_1(char a)
{cout << "char" << endl;
}
void print_1(int a, char b)
{cout << "int char" << endl;
}
void print_1(char b, int a)
{cout << "char int" << endl;
}
int main()
{print_1(50);print_1('a');print_1(60,'b');print_1('c',70);//根据参数自动匹配return 0;
}
可以看到这里,函数名都一样,只是参数的类型,个数,顺序不一样,只要一种或多种,都可以重载。
重载函数的底层原理:实际上这些函数在linux编译之后会产生不同的函数名,然后根据参数自动匹配不同函数的。
函数的默认参数(缺省参数)
#include<iostream>using namespace std;void test_1(int a = 10, int b = 20)//这里的int a = 10,被赋值10,说明只是一个默认参数
{cout << "a + b = " << a + b << endl;
}//注意1
//如果b设为默认参数,则从b往右的参数都必须设为默认参数
//也就是说,此时a不受影响,c是必须设为默认参数
//因为形参位置与实参位置保持一致,假设c没有默认参数
//调用test_2(100,200),这时,a,b都被赋值,c没有赋值,编译器就会报错(缺少参数)void test_2(int a, int b = 20, int c = 30)
{cout << "a + b = " << a + b << endl;
}
//还有值得注意的一点:如果函数声明与函数定义分开,想要设置默认参数,只需在声明里设置即可,函数定义无需再设。
int main()
{test_1();//可以什么参数都不传,这里就会使用默认参数test_1(30);//将30这个实参传给a,这时,函数就不会使用默认参数,而是a = 30;test_1(40, 50);//同理,此时a,b的默认参数失效, a,b的值因为 40 , 50return 0;
}
默认参数和函数重载的二义性
void fun(int a)
{cout << "a = " << a << endl;
}void fun(int a, int b = 20)
{cout << "a = " << a << endl << "b = " << b << endl;
}int main()
{fun(10);return 0;
}
此时编译器会报错:
什么意思呢?
就是说,此时调用fun(10)传入一个参数,既可以传给第一个fun,也可以传给第二个fun(第二个fun的第二个参数有默认参数,所以传入一个参数也正确),编译器不知到传给哪个fun,所以就报错 ,但如果这样调用fun(10,20)就是正确的,他会自动匹配到第二个fun。
占位参数
占位参数只有类型声明,没有参数名声明,一般情况下,函数体内部无法使用占位参数。
//形式一
void test_1(int a , int)
{;//这里的int就是占位参数
}
//形式二
void test_2(int a , int = 20)
{;//int = 20是占位参数,其实这里只是有一个隐形的参数名,但也只是表现形式,无法使用
}
int main()
{test_1(10, 20);//传参依然要传两个,并且类型对应,否则报错(缺少参数)test_2(10);//占位参数有缺省值,所以可以只传一个参数test_2(10, 20);//当然传两个也okkreturn 0;
}
也就是说,占位参数位置必须要传入参数,除非有缺省值。
至于怎么用,以后章节会细讲滴。
extern "C" 浅析
C++编译函数和C编译器编译函数的方式是不同的,假设定义一个Fun函数,经过C编译后会产生一个新的函数名叫Fun,而经过C++编译器编译后产生的新函数名可能(不同的C++编译器效果不一样)叫Funv,所以如果调用函数可能就会存在连接错误,那么为了能在C++的环境下调用C语言函数,就引入了extern "C",这部分代码也将按照C语言的编译方式取运行。
使用如下:
#if __cplusplus //检测当前是否是C++工程
extern "C"//满足则执行这里
{
#endif//不满足则执行这里,因为不满足说明就是C语言工程,直接引用以下就可以extern//引入你想要实现的C语言的函数声明//...;
#if __cplusplus
}
#endif
码字不易~
【C++】引用、内联函数、函数重载、函数默认参数(缺省参数)与占位参数、extern “C“ 浅析相关推荐
- C++内联(inline)函数
内联函数 内联函数是一种特殊类型的函数,内联函数在定义或声明时前面加上"inline"关键字.比如: inline int max(int a,int b) { return (a ...
- C++学习笔记之——引用 内联函数
本文为原创作品,转载请注明出处 欢迎关注我的博客:http://blog.csdn.net/hit2015spring和http://www.cnblogs.com/xujianqing/ 作者 ...
- C++ C++基础语法入门总结(二)引用-内联函数-C++11新特性
C++基础语法入门总结 C++引用 再谈引用和指针 C++内联函数 附加C++11新特性 auto关键字 基于范围的for循环 指针空值nullptr C++引用 引用:就是某一变量(目标)的一个别名 ...
- C++入门之命名空间、缺省函数、重载函数及引用
目录 一.命名空间 1.概念 (1)流插入运算符和流提取运算符 2.命名空间出现的意义 (1)c语言的命名缺陷 (2)如何解决命名冲突 3.命名空间的使用 (1)不展开使用 (2)完全展开使用 (3) ...
- matlab私有函数,MATLAB 嵌套函数,子函数,私有函数,重载函数
MATLAB函数嵌套 MATLAB中M文件有两种类型,脚本M文件和函数M文件.脚本M文件是将可执行程序语句放入M文件中,就像在命令窗口那样,按其语句顺序及逻辑关系执行,可以理解为一般的顺序执行程序语句 ...
- C++ 函数匹配 重载函数的调用规则
学习<C++ Primer>一书中,函数匹配这一节内容信息较多,现截取重点内容记录于此.便于你对本文内容更好的理解,你需对类型提升.算术类型转换以及顶层cosnt,底层const有一定的了 ...
- C# 虚函数和重载函数
虚函数就是在这个函数声明前加上virtual 这样这个函数在它的派生类(子类)中可以被重写 而子类在重写父类的虚函数时,要显式的加上override 用处:就是可以在子类中被重写,当你继承一个类时, ...
- C++文件头,命名空间,new和delete,内联函数,引用,函数重载,构造函数和析构函数,深拷贝和浅拷贝,explict,this指针
目 录 1 开始学习C++............................................................................... ...
- C++ 基础 : 函数重载、引用、内联函数、auto、范围for循环
函数重载 引用 内联函数 auto 范围for循环 函数重载 C++中引入了一个新特性,函数重载. 在同一个作用域下,对于相同的函数名,函数的参数不同,不同类型的参数顺序不同,参数的个数不同,都可以形 ...
- c++之头文件基本输出,输入,名字空间,引用,内联函数,函数重载,缺省参数
c++之头文件,基本输出,输入,名字空间,引用,内联函数,函数重载,缺省参数 文章目录 c++之头文件,基本输出,输入,名字空间,引用,内联函数,函数重载,缺省参数 前言 一.头文件,基本输出,输入 ...
最新文章
- 机器学习:信用风险评估评分卡建模方法及原理
- 正则表达式二 :贪婪与非贪婪
- JAVA_NIO ,走进JavaNIO的世界
- 2016计算机课程设计,2016年计算机组成原理课程设计-硬布线控制器的设计.doc
- 3-4 网络编程 练习题
- Python3 实现单例设计模式
- 手写table用ajax遍历,原生js把数据循遍历到前端table
- html5群组选择器,css选择器
- java 中的单引号报错_shell中的单引号,双引号,反引号
- linux协议栈网桥部分之cam表操作,Docker网络基础 - Linux网桥工作原理与实现
- IOS-播放器开发(1)-视频基本原理
- 【ADNI】数据预处理(2)获取 subject slices
- Lrc文件与音乐的同步显示
- JS内功修炼-基础篇
- 计算机二级word海报体,2016年计算机二级《MSOffice》全真模拟试题
- 高效人士的116个IT秘诀
- QT:模仿腾讯会议(低配版)
- IRQL深入解析(1)--IRQL级别
- 29_ElasticSearchIK中文分词器的安装和使用
- Android:实现安卓小程序-记事本(备忘录)的开发
热门文章
- asp.net mysql 查询_asp.net 多条件查询数据库
- android 人生日历,人生日历Android版 功能初体验
- 中国芯片人才大军在哪里?IEEE Fellow,投资人,创业者,工程师
- apk部分手机安装失败_安装apk解析包时出现错误怎么办?小编快速帮你解决
- E+H超声波物位计FMU42
- 保姆级人工智能学习成长路径
- 用ENSP华为模拟器做图书馆得网络配置和设计
- 一位资深程序员的亲身经历:跳槽国企要注意啥
- 计算机c盘加容量,两种方法,给电脑C盘增加10G的容量,电脑焕然一新
- 将系统必备组件打包进安装文件(以vs15打包.net formwork 4.5为例)有点鸡肋