• 新C++(1):命名空间\函数重载\引用\内联函数


     "你一无所有地闯荡"

    C++的出现,更多的是为了弥补C语言的不足。因此,很多C++的语法既支持C,也会在C中无法解决的问题,提供了自己解决的方法。 

    ---------前言

    (一)命名空间

    在一些代码工程量大的项目中,肯定不是单独由一个人完成的。这么多人使用成百上千的代码量,难免会出现自己定义的 变量名、函数......命名相同的情况。

    因此,为了解决这样的“命名冲突”的问题(或名字污染),提出了"namespace"关键字。 

     (1)命名域的使用

    ①普通使用: 

     因此与命名空间配合出现了一个操作符(域名操作符):"::"。

    ②命名空间嵌套使用(当然这很少):

    ③使用using 展开命名域

    (2)如何理解命名域和作用域

    我们知道,一个变量的作用域 其实是决定了它的生命周期的长短。

    那么处于命名空间里的变量,是定义在哪里的呢? 其作用域是多大,生命周期是多长呢?

    可以看出,全局变量 和 命名空间内变量的地址,是远远低于 在栈上开辟空间的b。

    因此,在命名空间里定义的变量,它的存储位置是在全局区。 那么它的生命周期 是随进程的。

    (3)如何理解using namespace std? 

    可能很多小伙伴,才初始C++的时候,总会看到"using namespace std"的字样,但是说到底,仍然不知道为什么要在main函数前 加这一句。

    其实本质上,std是C++库函数的一个命名空间,里面封装了很多函数接口。 

     这也就是为什么使用C++库函数的时候,要使用 域名访问操作符“::”。

    而我们也知道 using namespace + 域名其实就是把命名空间里的 变量、函数对外展开,也就是捅破了命名空间(std),对C++库中函数的包裹。

    但在实际中,很少会把std标准库里的内容展开。

    其根本原因是,难免会造成域外 定义的变量、函数 会和域内定义的命名冲突。
     

    根据就近原则,会优先在局部域内找到定义的  rand。 

    如果此时全局域出现一个rand,而又包含了含有rand的函数库 

     从而造成二义性的问题。

    ①半开放式的命名空间展开(using + 命名空间 + 变量、函数) 

    因此为了解决这样的问题,也就有了第三种处理这种问题的方式。


    (二)函数重载 

     在C中,如果我们要写一个加法,但是是适用多种类型的。

     同样是求两个数的和,功能完全一样,但是却要用不同的函数名进行区别,从函数的可读性来说,也不便于。

    (1)什么是函数重载

    是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这
    同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同,常用来处理实现功能类似数据类型不同的问题。

    C++引入“函数重载”后,从上层使用的角度上来看,调用的是同一个函数。但事实上,底层根据制定的规则,会去自动调用不同 的函数。 

     达成函数重载的三种情况

    ①参数类型不同

    ②参数个数

    ③参数顺序

    (2)函数重载的原理 

    可能你会疑问,为什么函数重载C++支持,而C语言不支持呢? 函数名修饰规则的不同

     

    可以看出在同一个函数Add下,C语言 下的函数名很简单。但是在C++下对函数修饰的规则做了进一步的修正。

    通过这里我们就可以理解了。因为C语言没有函数名修饰规则,也就无法区别同名函数。而C++引入了这一套规则,凭借“参数”(类型、个数、参数顺序)的不同修饰函数名,也就支持了重载。填入符号表,也就便于链接处找到对应的函数调用。

    函数重载 == 编译成功?

      

    但函数在调用时,会出现问题!

     

    其原因就是 函数调用出现了二义性,导致调用函数位置处指名不明确。 

     


    (三)引用 

    什么是引用呢?

    引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。

    (1)如何使用引用? 

    ①引用语法 

    形如如上,就是一个变量的引用。可以显然的看到,引用就是一个数的别名。它就是这个数 

    ②引用特性

     定义时必须初始化;

     一个变量可以有多个引用;

     引用一旦引用一个实体,再不能引用其他实体;

     ③引用与const 

     

     ④引用的参数与返回值

    当用C语言写Swap交换函数时,是用的指针。但C++引入引用后,完全可以替代。 

    引用还可以作为参数返回。

    1. int& func()
    2. {
    3. static int a = 3;
    4. return a;
    5. }

    看看下面代码,如果引用返回会有什么结果?

    1. int& Add(int x, int y)
    2. {
    3. int c = x + y;
    4. return c;
    5. }
    6. int main()
    7. {
    8. int& ret = Add(3, 4);
    9. cout << ret << endl;
    10. return 0;
    11. }

     因此为了避免这样的 引用乱用的情况。 

     如果返回值 在出了函数作用域仍然存在,那么此时可以进行引用返回。

     否则,一定不行(仅仅是在此时此刻这么认为!!!)。

    (2)引用与指针 

    根本上,引用的出现,就是为了 简化C语言的指针。因为其实在太灵活和复杂。

    虽然本质上,引用在底层上就是由指针实现的。但在语法层面上,两者应当区别开来。 

    ①指针与引用的区别 

    1.在概念上引用是一个变量的别名,指针存储的是一个地址。

    2.引用在定义时必须初始化,指针可以为空。

    3.引用只能引用一个实体,指针任何时候可以指向不同实体。

    4.sizeof(引用) 数据类型大小,sizeof(指针) 地址空间大小。

    5.++ -- 的不同。引用数值变化,指针地址变化。

     

    (3)引用的反思 

     引用语法的引入是很成功的。

     单从引用作为参数返回、传入时,减少了非必要的拷贝,大大提高了运行时效率。

     与指针想比,其使用起来简单,没有指针那么复杂,且相对安全。

    注:本段所讲的引用,均为 “左值引用!!!”


    (四)内联函数 

    什么是内联函数?

    以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数调用建立栈帧的开销,内联函数提升程序运行的效率。

    从内联函数的概念上来说,轻而易举知道,该函数就是为了避免 当一个函数频繁调用时,减少建立栈帧的开销。 

    (1)宏函数 和 内联函数

     内联函数的功能,就是在执行到调用函数处,不再为之开辟栈帧,而是直接将函数内的代码就地进行展开。

    看到如此的使用形式,不禁想起C中也有一种同等类似 形式的函数。-------宏函数

    我们知道宏函数的本质,就是文本替换,在预处理的时候 就会在标志处进行文本替换。

    那么宏函数有什么缺点呢? 

    1.没有严格类型检查,你传double进去 也给你相加

    2.无法调试

    3.易错 

    为什么易错? 

     因此内联函数的出现,恰恰就是为了弥补 宏函数的缺点!

    debug版本下可以进入调试

    (2)内联函数的特性

    inline函数 是一种 以空间 换时间的做法。

    缺陷:让可执行程序(obj目标文件)变大

    优点:提高程序的运行效率

    ①编译器决定是否内联展开 

    但对于编译器而言,是否选择内联由编译器决定。正如初始C时,将常用变量存入寄存器中一样。

    当内联函数足够长时,就算标明了内联属性,但编译器仍然会把它当成普通函数处理。建立栈帧。 

     

    如何理解不建议内联函数 定义、声明分离! 

     

    本质在于,设置为内联的函数,不会被添加进符号表。

    那么当链接时,拿着函数名找不到对于的函数地址! 


    总结

    ①命名空间存在的意义在于,避免“命名冲突”。

    ②库函数的三种用法:std::+函数名 \ using std::+函数 \ using namespace std;

    ③函数重载在C++中支持的根本,是引入了函数名修饰规则。

    ④重载特性:参数类型不同 ||个数不同 || 顺序不同

    ⑤引用就是一个变量的别名。

    ⑥引用与指针的区别、引用作为参数、返回值、引用与const。

    ⑦内联函数与宏函数区别

    ⑧内联函数的特点。


    本篇到此结束

    感谢您的阅读~

    祝你好运 

  • 相关阅读:
    SwiftUI 原生或利用 Vision 检测限定高度的 Text 视图能否完整显示文本的方法
    java基于Springboot+vue的健身房课程预约平台 element
    无代码开发打印模板入门教程
    考研数据结构填空题整合
    Yolo v8 目标识别 单目测距 速度检测
    力扣每日一题43:字符串相乘
    Proxy代理配置解析
    磁选机是什么?
    图的深度优先遍历
    Vue学习第25天——Vuex中的4个map方法的基本用法及案例练习
  • 原文地址:https://blog.csdn.net/RNGWGzZs/article/details/126961529