iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++ 引用与内联函数实例分析
  • 772
分享到

C++ 引用与内联函数实例分析

2023-06-30 13:06:15 772人浏览 独家记忆
摘要

这篇文章主要介绍“c++ 引用与内联函数实例分析”,在日常操作中,相信很多人在C++ 引用与内联函数实例分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C++ 引用与内联函数实

这篇文章主要介绍“c++ 引用与内联函数实例分析”,在日常操作中,相信很多人在C++ 引用与内联函数实例分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C++ 引用与内联函数实例分析”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

引用初阶

引用是C++的特性的之一,不过C++没有没有给引用特意出一个关键字,使用了操作符的重载。引用在C++中很常见,常见就意味着它很重要。我们分两个境界来谈谈引用,初阶是我们能在书上看到的.

什么是引用

引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间 .所谓的取别名,就是取外号,张三在朋友面前可能叫三子,在长辈面前可能叫三儿,但是无论是叫三子还是三儿,他们叫的就是张三,这是无可否认的.引用的符号&和我们取地址的&操作符一样的,后面我们就会知道这是操作符构成重载的原因.

我们可以理解所谓的引用.

#include <stdio.h>int main(){int a = 10;int& b = a;       //  b 是 a的一个别名printf("%p\n", &a);printf("%p\n", &b);return 0;}

C++ 引用与内联函数实例分析

为何要有引用

引用有很多优点,其中有一个就是可以简化代码,我们在C语言中写过如何交换两个整型数据,需要借助一维指针,但是这有一点麻烦,使用引用就可以很好的解决这个问题.

#include <stdio.h>void swap(int& a, int& b){int c = a;a = b;b = c;}int main(){int a = 10;int b = 20;printf("交换前  a = %d b = %d\n", a, b);swap(a, b);printf("交换后  a = %d b = %d\n", a, b);return 0;}

C++ 引用与内联函数实例分析

引用指向同一块空间

我们无论给变量取多少外号,但是这些外号所指向的空间是一样的,我们只要修改一个外号的空间,就会导致其他外号值得修改.

#include <iOStream>using namespace std;int main(){int a = 10;int& b = a;  //b 是  a  的别名int& c = b;  //还可以对c取别名return 0;}

C++ 引用与内联函数实例分析

int main(){int a = 10;int& b = a;  //b 是  a  的别名int& c = b;  //还可以对c取别名c = 20;cout << "a: " << a << endl;cout << "b: " << a << endl;cout << "c: " << a << endl;return 0;}

C++ 引用与内联函数实例分析

引用的特性

即使引用很好使用,但是我们还要关注他们的一些特性.

定义时必须初识化

这个要求很严格,我们必须在引用的时候给他初始化,否则就会报错.

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

C++ 引用与内联函数实例分析

一个变量可以多次引用

这个特性我们前面和大家分享过了,我们可以对一个变量多次取外号,每一个外号都是是这个变量的别名,我们甚至可以对外号取外号,不过我们一般不这么干.

引用一旦引用了一个实例,不能在再引用其他的实例

这个特性完美的阐释了引用的专一性,一旦我们给某一个变量起了一个别名,这个别名就会跟着这个变量一辈子,绝对不会在成为其他的变量的别名.这个也是和指针很大的区别,指针比较花心.

这个我们就不通过代码打印各个变量的地址了.,我们观看另外一种现象,通过观察我们看到a的值也被修改了,可以确定 b 仍旧a的别名.

int main(){int a = 10;int& b = a;int c = 20;// 这个一定是赋值b = c;cout << "a: " << a << endl;return 0;}

C++ 引用与内联函数实例分析

引用进阶

我们已经看到引用的优点,但是这是引用的基础用法,要是到那里,我们一般看书都可以做到,现在要看看引用更加详细的知识.

常引用

我们在C语言中,专门分享过const相关的知识,那么我们如何对const修饰的变量取别名呢?这是一个小问题.

const int a = 10;

我们看看下面的方法.

int main(){const int a = 10;int& b = a;        //报错const int& c = a;  // 不报错return 0;}

C++ 引用与内联函数实例分析

到这里我们就可以发现,我们取别名的时候也用const修饰就可以了,这是我们从现象中的得出的结论,但是这又是因为什么呢?我们需要知道他们的原理.

权限

不知道大家有没有在学习中看到过这样一种现象,对于一个文件,我们可能存在仅仅阅读的权限,自己无法修改,但是其他的人有可能有资格修改,这就是权限的能力,const修饰变量后,使得变量的加密程度更加高了,我们取别名的时候,总不能把这个权限给过扩大了,编译器这是不允许的,也就是说我们取别名的时候,权限只能往低了走,绝对不能比原来的高.

下面就是把权限往缩小了给

int main(){    int a = 10;const int& b = a;return 0;}

C++ 引用与内联函数实例分析

常量取别名必须要是const修饰的,因为常量不能修改.

int main(){const int& a = 10;return 0;}

C++ 引用与内联函数实例分析

临时变量具有常属性

这个是语法的一个知识点,我们记住就可以了,现在我们就要看看为什么这个代码会可以运行.

我们常引用 还有最后一个问题,如果我们是double类型的变量,如何给取一个int类型的别名?

需要用const修饰,而且会发生截断,

int main(){double d = 1.2;const int& a = d;       //需要用const修饰cout << a << endl;return 0;}

C++ 引用与内联函数实例分析

它的本质不是取别名,而类似于给常量取别名,而且还会发生截断.这个说截断也不太合适,这会产生一个临时变量,我把原理图放在下面.

int main(){double d = 1.2;const int& a = d;cout << "&a :" <<&a << endl;cout << "&d :" <<&d << endl;return 0;}

C++ 引用与内联函数实例分析

引用的场景

我们需要来看看引用的使用场景,它主要有两大作用.

  • 做参数

  • 做返回值

做参数

我们可以使用引用来交换两个整型数据.

#include <stdio.h>void swap(int& a, int& b){int c = a;a = b;b = c;}int main(){int a = 10;int b = 20;printf("交换前  a = %d b = %d\n", a, b);swap(a, b);printf("交换后  a = %d b = %d\n", a, b);return 0;}

C++ 引用与内联函数实例分析

但是使用引用作为参数可能会出现权限不太匹配的错误,所以说我们需要const修饰.

下面就是由于权限问题,我们没有办法来给常量却别名,这就需要const修饰.

void func(int& a){}int main(){int a = 10;double b = 10.2;func(a);func(10);func(b);return 0;}

C++ 引用与内联函数实例分析

返回值

我们先看看返回值的原理,再说说引用做返回值.

返回值的原理:

我们需要谈谈编译器是如何使用返回值的,以下面的代码为例.

int func(){int n = 1;n++;return n;}int main(){int ret = func();return 0;}

编译器会看这个返回值的空间大不大,如果不大,就把的数据放到一个寄存器中,如果很大,看编译器的机制,有的编译器甚至可能在main函数中开辟这个空间来临时保存数据.

这是由于当函数结束后,函数栈帧会销毁,n的空间也会被释放,所以要有一个寄存器来保存数据.

C++ 引用与内联函数实例分析

下面的代码就可以表现出来:

int main(){int& ret = func();return 0;}

C++ 引用与内联函数实例分析

引用做返回值

引用做返回值会有很大的要求,这个和我们普通的返回值可不一样.说实话,我不想和大家分享的那么深,但是已经到这里了,只能这样了.

下面的代码,我们可以理解,就是给静态变量n取一个别名,我们把它返回到了ret.

int& func(){static int n = 1;n++;return n;}int main(){int ret = func();cout << ret << endl;return 0;}

C++ 引用与内联函数实例分析

也就是说我们n取一个别名,把这个别名作为返回值返回给函数调用者.

int& func(){static int n = 1;n++;cout << &n << endl;return n;}int main(){int& ret = func();     //  注意 是 int&cout << &ret << endl;return 0;}

C++ 引用与内联函数实例分析

注意事项:

到这里我们就可以看看引用做返回值的注意事项了,我们一定要保证做返回值得引用得数据在函数栈帧销毁后空间不被释放,否则就会发生下面得事情.

我们得到的是一个随机值,我们拿到了变量 n 的别名,但是在func结束后空间就被释放了,下一次函数的调用函数栈帧会覆这篇空间,运气好的话,我们有可能拿到准确值,但是无论如何访问都越界了.

int& func(){int n = 1;n++;return n;}int main(){int& ret = func();printf("这是一条华丽的分割线\n");cout << ret << endl;cout << ret << endl;return 0;}

C++ 引用与内联函数实例分析

引用不会开辟空间

前面我们说了传参需要有一定的要求,但是这不是说引用做参数不行,我们使用引用传参不会发生拷贝,这极大的提高了代码的效率.

我们定义一个大点的结构体,来看看拷贝传参和引用传参的效率.一般情况下相差大概20倍左右.

typedef struct A {int arr[10000];} A;void func1(A a){}void func2(A& a){}void TestRefAndValue(){A a;// 以值作为函数参数size_t begin1 = clock();for (size_t i = 0; i < 100000; ++i)func1(a);size_t end1 = clock();// 以引用作为函数参数size_t begin2 = clock();for (size_t i = 0; i < 100000; ++i)func2(a);size_t end2 = clock();// 分别计算两个函数运行结束后的时间cout << "func1(A)-time:" << end1 - begin1 << endl;cout << "func2(A&)-time:" << end2 - begin2 << endl;}int main(){TestRefAndValue();return 0;}

C++ 引用与内联函数实例分析

引用和指针比较

它们有一个本质的区别,在语法概念上引用就是一个别名,没有独立空间,和其引用实体共用同一块空间 ,但是引用的底层还是开辟空间的,因为引用是按照指针方式来实现.我们看看汇编代码.

  • 引用不会开辟空间,但是指针会开辟相应的空间.

底层引用和指针是一样的.

int main(){int a = 10;//语法没有开辟空间  底层开辟了int& b = a;b = 20;//语法开辟空间  底层也开辟了int* pa = &a;*pa = 20;return 0;

C++ 引用与内联函数实例分析

我们来看看它们其他的比较小的区别,我就不详细举例了.

  • 引用在定义时必须初始化,指针没有要求

  • 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体

  • 没有NULL引用,但有NULL指针

  • sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节)

  • 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小

  • 有多级指针,但是没有多级引用

  • 访问实体方式不同,指针需要显式解引用,引用编译器自己处理

  • 引用比指针使用起来相对更安全

内联函数

以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数压栈的开销,内联函数提升程序运行的效率,本质来说就和我们的宏比较相似.

记住我们不关心他们在那个过程中展开,只需要记住他会展开就可以了.我么看看内联函数的知识点.

为何存在 内联函数

对于一些比较小的函数,我们总是调用函数开销比较的,我们是不是存在一个方法减少这个开销呢?C语言通过宏来实现,C++支持C语言,所以我们可以通过行来实现,那么你给我写一个两数现相加的宏,要是你写的和下面的不一样,就代表你忘记了一部分知识点.

#define ADD(x,y) ((x) + (y))       //不带  ;   括号要带

我们就可以理解了,宏很好,但是写出一个正确的宏很困难,但是写一个函数就不一样了,所以一些大佬就发明了内敛函数,用来替代宏的部分功能.

展开短小的函数

函数内联不内联不是你说了算,我们用inline修饰就是告诉编译器这个函数可以展开,至于是否展开还是看编译器,一般之后展开比较短小的函数,较大的函数不会展开,像递归的那些也不可以.

inline void swap(int& x, int& y){int ret = x;x = y;y = ret;}int main(){int a = 1;int b = 2;swap(a,b);cout << "a: " << a << endl;cout << "b: " << b << endl;return 0;}

C++ 引用与内联函数实例分析

我们来看看内联函数,如果函数不是内联了的,汇编语言会call

void swap(int& x, int& y){int ret = x;x = y;y = ret;}

C++ 引用与内联函数实例分析

如果在上述函数前增加inline关键字将其改成内联函数,在编译期间编译器会用函数体替换函数的调用.

由于我们使用的是VS编译器,这里需要看看内联函数的汇编语言.

在release模式下,查看编译器生成的汇编代码中是否存在call swap,但是编译器会发生优化,我们通过debug模式下,但是需要设置.

C++ 引用与内联函数实例分析

inline修饰的较短函数展开了,没有call

inline void swap(int& x, int& y){int ret = x;x = y;y = ret;}

C++ 引用与内联函数实例分析

内联函数的特性

我们需要来看看函数的基本的特性

  • inline是一种以空间换时间的做法,省去调用函数额开销。所以代码很长或者有循环 / 递归的函数不适宜使用作为内联函数。

  • inline 对于编译器而言只是一个建议,编译器会自动优化,如果定义为inline的函数体内有循环/递归等,编译器优化时会忽略内联。

  • inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到。

较大的函数编译器不会发生内联

编译器会自动判别这个函数给不该内联,要是一个函数比较大,里面存在递归,那么还不如不展开呢.一般是10行为依据.

inline void f(){cout << "hello" << endl;cout << "hello" << endl;cout << "hello" << endl;cout << "hello" << endl;cout << "hello" << endl;cout << "hello" << endl;cout << "hello" << endl;cout << "hello" << endl;cout << "hello" << endl;cout << "hello" << endl;cout << "hello" << endl;cout << "hello" << endl;cout << "hello" << endl;cout << "hello" << endl;cout << "hello" << endl;cout << "hello" << endl;cout << "hello" << endl;cout << "hello" << endl;}int main(){f();return 0;}

C++ 引用与内联函数实例分析

声明定义一起

如果我们声明和定义的分离,运行时编译器会找不到这个函数的地址的.

C++ 引用与内联函数实例分析

C++ 引用与内联函数实例分析

这里我么建议直接把内联函数直接放到自定义的头文件中

inline void f(){}

C++ 引用与内联函数实例分析

到此,关于“C++ 引用与内联函数实例分析”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

--结束END--

本文标题: C++ 引用与内联函数实例分析

本文链接: https://www.lsjlt.com/news/329307.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C++ 引用与内联函数实例分析
    这篇文章主要介绍“C++ 引用与内联函数实例分析”,在日常操作中,相信很多人在C++ 引用与内联函数实例分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C++ 引用与内联函数实...
    99+
    2023-06-30
  • C++ 引用与内联函数详情
    目录引用初阶什么是引用为何要有引用引用指向同一块空间引用的特性定义时必须初识化一个变量可以多次引用引用一旦引用了一个实例,不能在再引用其他的实例引用进阶常引用权限临时变量具有常属性引...
    99+
    2024-04-02
  • C++引用与内联函数怎么使用
    这篇文章主要介绍“C++引用与内联函数怎么使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“C++引用与内联函数怎么使用”文章能帮助大家解决问题。一、引用首先我们来看一下引用的概念:1.1引用的概念...
    99+
    2023-07-05
  • c++内联函数怎么引用
    在C++中,内联函数是通过将函数的定义放在每个调用点处进行替换,而不是通过函数调用来实现的。因此,在引用内联函数时,需要确保函数的定...
    99+
    2023-10-26
    C++
  • Python与C++的引用实例分析
    这篇文章主要讲解了“Python与C++的引用实例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Python与C++的引用实例分析”吧!例子,这是我的两段根据先序序列创建二叉树的代码:#...
    99+
    2023-06-27
  • C++内联函数不宜使用情况的示例分析
    这篇文章将为大家详细讲解有关C++内联函数不宜使用情况的示例分析,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。C++语言中的各种应用是一个非常高深的内容,其中的语法、特性、标准类库都是我们值...
    99+
    2023-06-17
  • C++深入分析内联函数的使用
    目录一、常量与宏回顾二、内联函数三、内联函数使用注意事项四、小结一、常量与宏回顾 C++中的const常量可以替代宏常数定义,如︰ 但是C++中是否有解决方替代宏代码片段呢?这里就...
    99+
    2024-04-02
  • C++11中内联函数(inline)用法实例
    目录inline 是什么?引入inline的目的是什么?内联函数的特点内联函数的写法隐式内联和显式内联inline 函数的编译器处理内联函数优缺点虚函数可以是内联函数吗?虚函数内联条...
    99+
    2022-11-13
    c++内联函数定义 c++11内联函数 inline怎么用
  • C#中条件编译、内联函数、CLS的示例分析
    这篇文章主要为大家展示了“C#中条件编译、内联函数、CLS的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“C#中条件编译、内联函数、CLS的示例分析”这篇文章吧。1、条件编译#if&nb...
    99+
    2023-06-29
  • C++ 内联函数的代码生成分析
    c++++ 内联函数是在编译时展开的函数,消除了函数调用的开销。它们适用于轻量级操作、经常调用的函数以及需要避免函数调用开销的函数。然而,使用内联函数时要注意代码膨胀和优化限制。 C+...
    99+
    2024-04-29
    c++ 内联函数
  • C++超详细分析讲解内联函数
    目录宏函数(带参数的宏)的缺点inline修饰的函数就是内联函数内联函数的特点宏函数和内联函数的区别宏函数(带参数的宏)的缺点 第一个问题:宏函数看起来像一个函数调用,但是会有隐藏一...
    99+
    2024-04-02
  • C++浅析内联函数的使用
    目录一. 概念二. 特性一. 概念 以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数压栈的开销, 内联函数提升程序运行的效率。 在C++里...
    99+
    2024-04-02
  • C++引用的定义与使用实例分析
    这篇文章主要介绍了C++引用的定义与使用实例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C++引用的定义与使用实例分析文章都会有所收获,下面我们一起来看看吧。解释引用首先我们先来看一个引用的例子int&n...
    99+
    2023-07-02
  • C++函数参数实例分析
    这篇文章主要介绍了C++函数参数实例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C++函数参数实例分析文章都会有所收获,下面我们一起来看看吧。一、函数参数的默认值C++ 中可以在函数声明时为参数提供一个默...
    99+
    2023-06-30
  • Python与C++引用的示例分析
    本篇文章给大家分享的是有关Python与C++引用的示例分析,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。在用Python写建二叉树的代码的时候遇到了这个问题,原因就是把Pyt...
    99+
    2023-06-02
  • C语言函数使用实例分析
    这篇文章主要介绍了C语言函数使用实例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C语言函数使用实例分析文章都会有所收获,下面我们一起来看看吧。函数的声明和定义函数声明告诉编译器有一个函数叫什么,参数是什么...
    99+
    2023-06-30
  • C++ 内联函数inline案例详解
    使用函数能够避免将相同代码重写多次的麻烦,还能减少可执行程序的体积,但也会带来程序运行时间上的开销。 函数调用在执行时,首先要在栈中为形参和局部变量分配存储空间,然后还要将实参的值复...
    99+
    2024-04-02
  • C++ 内联函数与虚拟函数的异同
    内联函数将函数体嵌入调用点,提升性能和代码体积,但可读性较低;虚拟函数通过多态性调用子类覆写的函数,提高灵活性,但运行时开销较高。 C++ 内联函数与虚拟函数的异同 内联函数 内联函数...
    99+
    2024-04-17
    内联函数 虚拟函数 c++ 代码可读性
  • C++ 内联函数与函数指针的区别
    内联函数直接展开而不调用,而函数指针存储指向函数地址的变量,允许间接调用函数。 C++ 内联函数和函数指针的区别 什么是内联函数? 内联函数是编译器在编译时直接展开的函数。这意味着内联...
    99+
    2024-04-16
    函数指针 内联函数 c++
  • C++ 内联函数与宏的对比
    内联函数展开为代码,消除调用开销,但避免函数体过大和递归调用;宏是文本替换,轻量级但难维护,用于常量和简短代码片段。实战案例:内联函数实现斐波那契数列,宏定义常量 pi。 C++ 内联...
    99+
    2024-04-17
    c++ 内联函数 堆栈溢出
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作