文章目录

  • 函数重载
  • 为什么C++支持重载,C语言不支持呢?
  • extern “C”
  • 引用再探
    • 引用的特性
    • 引用的使用场景
    • 引用和指针
    • 引用和指针的不同点:
  • 内联函数
    • 什么是内联函数?
    • 内联函数的特性
    • 内联函数的好处
    • 类的内联成员函数的声明
  • constexpr函数
    • 概念
    • 特征
    • 内联函数和constexpr函数放在头文件内

函数重载

在同一个作用域下,对于相同的函数名,函数的参数类型不同,参数顺序不同,参数的个数不同, 都可以形成函数的重载(参数名不同,返回值不同不形成重载)

函数的重载主要用于处理功能相同,形参类型不同的数据。

void test(int i, int j)
{cout << "test" << endl;
}void test(double i, int j) // 类型不同
{cout << "test" << endl;
}void test(int j, double i) // 顺序不同
{cout << "test" << endl;
}void test(double i, int j, int k) // 个数不同
{cout << "test" << endl;
}

为什么C++支持重载,C语言不支持呢?

因为windows对函数重载的处理更加复杂,所以这里用linux下的gcc和g++来看更加直观。

首先我们要知道,链接器看到有函数被调用的时候,就会到符号表中去查找对应的函数名,来获取函数的地址,再链接到一起

先看C语言是怎么处理的


通过反汇编我们可以看到,C语言并没有对函数名进行处理,也就是说无论我们参数的个数,参数的类型,参数的顺序怎么修改,它只认函数名,如果出现了第二个相同函数名的,就算重定义。

下面再看C++的:


这里可以看到,C++对函数名进行了处理,函数以_Z4开头,接着是函数名,最后是所有参数的缩写。

_Z是所有函数的前缀,4是函数名的字符个数,例如第一个_Z4testii则代表函数名为test,具有四个字符,参数类型缩写分别是ii。

这也就是为什么返回值不同和参数名不构成重载的原因,它们不被作为对函数特征的处理。C++正是通过这种函数名修饰规则来实现函数的重载。


extern “C”

有时候我们在使用C++的时候,对于某些函数,想让它按照C的风格来编译,那么就在函数前加extern “C”,意思是告诉编译器,将该函数按照C语言规则来编译。


引用再探

引用的特性

  1. 引用在定义的时候必须初始化(因为引用是某个对象的别名,所以必须初始化)
  2. 一个对象可以有多个引用
  3. 一旦引用一个实体,就不能再引用别的实体(有点类似指针的顶层const)

引用的使用场景

  1. 作为参数
struct A
{int arr[1000000];
};void test(A& s1)
{}

假设我们存在一个超级大的结构体,如果我们直接将结构体传过去的话,会产生一个临时变量来将这个结构体拷贝到形参中,这是极大的开销,但如果我们使用引用的话,传的只是一个别名而已,所有的操作还是在结构体本身上进行的,但是需要注意的和上面一样,如果我们要传递一个常量,就必须要在引用前加上const。

struct A
{int arr[1000000];
};void test (const A& s1)
{}
int main(int argc, char const *argv[])
{const A a = {10,324,32};test(a);return 0;
}
  1. 作为返回值
int& Add(int a, int b)
{int c = a + b;return c;
}int main()
{int& ret = Add(1, 2);Add(3, 4);cout << ret << endl;return 0;
}

对于这样一个代码,我们可能第一眼觉得ret会是3。

但是其实是7。

因为我们返回的是c的一个引用,但是c只存在于调用时的那个栈帧,调用结束后那个栈帧就会被销毁,虽然销毁后数据不会被清空,但是那片区域的访问权限就会被放开,有可能会被下次调用的函数使用,也有可能会被其他的一个操作给使用,所以这是一种极为不安全的行为。

上面的7是第二次调用后修改了c的值。

所以,如果需要引用作为返回值,就必须保证出了函数作用域,返回的对象没有归还给系统,仍然存在。

以值作为参数或者返回值时,在传参和返回的时候,都会传递或返回原变量的一个临时的拷贝,这样的效率是非常低下的,尤其是数据特别大的时候,但如果使用引用作为参数的话,就不会有这样的问题。

引用和指针

语法概念上:引用是对象的一个别名,没有独立的空间,和其引用的实体共用一个空间。

但我们发现,引用其实和指针很像,它更像一个顶层const的指针,所以我们可以进入反汇编看看他们之间有没有关系

int main()
{int x = 5;int& y = x;int* z = &x;return 0;
}


反汇编下我们可以看到,指针和引用在汇编下的实现是一模一样的。

所以我们可以得出一个结论:引用是按照指针来实现的,在指针的基础上又给他封装了新的功能。

引用和指针的不同点:

  1. 引用在定义时必须初始化,指针没有要求
  2. 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型 实体
  3. 没有NULL引用,但有NULL指针
  4. 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占 4个字节)
  5. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
  6. 有多级指针,但是没有多级引用
  7. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理
  8. 引用比指针使用起来相对更安全

内联函数

什么是内联函数?

用inline关键字修饰的函数就是内联函数,在编译时编译器会将函数的代码在调用内联函数的地方展开,减去了函数压栈的开销,提升程序运行的效率(牺牲空间换取时间)。

例如这样一个简单的代码
如果我们直接调用它

在汇编下可以看到,他会创建一个新的栈帧,将参数3,4压栈,然后计算完再返回结果

而如果在函数前面加上inline使其变为内联函数

这时再看,就会发现它直接把函数的代码在调用处直接展开,不会再创建新的栈帧。

内联函数的特性

  1. 内联函数是一种用空间换时间的做法,省去了创建栈帧和压栈的开销,但也因此代码很复杂和具有循环或递归之类的函数不适合作为内联函数,就算声明为内联函数编译器也会自动将其忽略。
  2. 内联函数不能声明和定义分离,因为一旦声明为内联函数,在调用的时候就会直接展开,没有了函数的地址,就无法将其链接到定义的部分。

值得一提的是,内联函数与C语言中的宏函数有些类似,虽然宏的性能不错,但是因为宏缺乏类型的安全检查和无法调试(在预处理阶段就进行了宏替换),在C++中宏函数被内联函数替代,宏常量定义被const取代。

内联函数的好处

  1. 较之等价的表达式更易于阅读
  2. 可以被其他应用重复利用,省去了重新编写的代价
  3. 如需修改计算过程,显然修改函数比先找到等价表达式所有出现的地方再逐一修改更容易。

类的内联成员函数的声明

我们可以在类内把inline作为声明的一部分显式地声明成员函数,同样的,也能在类的外部用inline关键字修饰函数的定义(当然在声明和定义的地方同时说明inline也是合法,只是没有必要)。


constexpr函数

概念

能用于常量表达式的函数

特征

  1. 函数的返回类型及所有形参的类型都得是字面值类型
  2. 函数体中必须有且只有一条return语句
  3. 编译器把对constexpr函数的调用替换成其结果值(constexpr函数被隐式地指定为内联函数)
  4. 函数体内允许包含 运行时不执行任何操作的语句
  5. 允许返回一个非常量,应用时编译器会进行检查。(constexpr不一定返回常量表达式)

内联函数和constexpr函数放在头文件内

和其他函数不同,内联函数和constexpr可以在程序中多次定义(每一次展开就是一次定义)。但多个定义必须完全一致,基于这个原因,内联函数和constexpr函数通常定义在头文件。

函数重载、引用再探、内联函数相关推荐

  1. 【C++之函数】引用符号、内联函数inline、函数重载

    文章目录 引用(&)是标识符的别名 内联函数(关键字:inline) 函数重载 引用(&)是标识符的别名 声明一个引用指向一个对象,则只是为对象的别名,其本身同所指对象保持一致. 例如 ...

  2. c++入门 有关《c++关键字》 《命名空间》《缺省参数》《函数重载》《引用》《内联函数》《outo关键字》

    1.C++关键字(c++98) C++总共63个关键字,c语言一共32个关键字. 下面我列 举出c++的关键字: 2.命名空间 在c/c++中,变量,函数和后面要学到的类都是大量存在的,这些变量,函数 ...

  3. 内联函数什么时候展开_内联函数

    内联函数什么时候展开 You know all of those Util files you create with all sorts of small functions that you en ...

  4. 内联函数有什么优点?内联函数和宏定义的区别

    用内联函数取代宏: 1.内联函数在运行时可调试,而宏定义不可以; 2.编译器会对内联函数的参数类型做安全检查或自动类型转换(同普通函数),而宏定 义则不会: 3.内联函数可以访问类的成员变量,宏定义则 ...

  5. c语言内联函数加static,Static和内联函数

    1.在C语言中,关键字Static有三个明显的作用: --- 在函数体内,一个被声明为静态的变量在这一函数被调用结束后不释放其存储空间.定义为static的局部变量存储在全局区(静态区),而一般的局部 ...

  6. 内联函数有什么优点?内联函数与宏定义的区别?

    内联函数的优点 内联函数比宏定义更加的安全,因为前者进行参数检查,而后者仅仅是简单地文本替换. 内联函数和宏定义的区别 宏定义是在预处理阶段进行的文本替换. 内联函数是在编译阶段进行的替换,优点是减少 ...

  7. c语言内联函数的声明,C语言内联函数

    一般来说,调用一个函数流程为:当前调用命令的地址被保存下来,程序流跳转到所调用的函数并执行该函数,最后跳转回之前所保存的命令地址. 对于需要经常调用的小函数来说,这大大降低了程序运行效率.所以,C99 ...

  8. Linux中内联函数,Windows 7上的内联函数的doParallel问题(适用于Linux)

    我在 Windows 7和 Linux(SUSE Server 11(x86_64))上都使用R 3.0.1.以下示例代码在Windows上产生错误,但在Linux上不产生错误.列出的所有工具箱在两台 ...

  9. C++ 基础 : 函数重载、引用、内联函数、auto、范围for循环

    函数重载 引用 内联函数 auto 范围for循环 函数重载 C++中引入了一个新特性,函数重载. 在同一个作用域下,对于相同的函数名,函数的参数不同,不同类型的参数顺序不同,参数的个数不同,都可以形 ...

最新文章

  1. 等待队列wait queue
  2. Xamarin Android真机测试报错
  3. Python100入门题 | 第001题
  4. r shiny内部支持的输入函数
  5. boost::fusion::single_view用法的测试程序
  6. svnsync实现版本库的同步备份
  7. 就两本书?还能吊起相扑选手?
  8. Python 源码剖析(二)—— 第一次修改 Python 源代码
  9. Unity3d UGUI 通用Confirm确认对话框实现(Inventory Pro学习总结)
  10. (十一)RabbitMQ消息队列-如何实现高可用
  11. JSjavascript获取B站封面图片超高清批量下载原图
  12. 弹窗拦截小帮手------火绒
  13. 欧几里得算法(求解最大公约数的优质方法)以及原理拓展
  14. C语言 将一个3*3的矩阵转置,用函数和指针实现
  15. 如何用matlab绘制心形线,心形线的matlab程序
  16. CSS——微信朋友圈图片样式实现方法
  17. DDos攻击解析(附现状和案例)
  18. php毕业论文致谢,zpw2000毕业论文致谢(本科毕业论文致谢词范文)
  19. uniapp微信小程序引入第三方字体库
  20. ios客户端学习笔记(七):iOS客户端的UI设计

热门文章

  1. 怎么用计算机打分数,电脑excel中分数怎么打出来(图解excel分数输入法)
  2. mysql pmm 布署_给 mysql 安装 pmm 监控
  3. find_path、find_library备忘录
  4. linux下gsoap的初次使用 (c)
  5. vector利用swap()函数进行内存的释放
  6. Asterisk realtime 之SIP用户动态写入mysql 数据库
  7. linux 字符串截取_linux下可执行文件分析
  8. 【转】VTK修炼之道2_VTK体系结构1
  9. 【转】WebApi中的C#await / async,重点是什么?
  10. python可以开发驱动吗_Python机器学习实践:测试驱动的开发方法