C++基础(命名空间,为什么C++可以函数重载,应用,内存结构)

命名空间:

在C/C++中,变量、函数和类都是大量存在的,如果这些变量、函数和类的名称将都存在于全局作 用域中,可能会导致很多冲突。为了解决命名冲突 ,C++中引入了命名空间,所谓命名空间就是一个可以由用户自己定义的作用域,在不同的作用域中可以定义相同名字的变量,互不干扰,系统能够区分它们。

缺省参数
缺省参数是声明或定义函数时为函数的参数指定一个默认值。在调用该函数时,如果没有指定实参则采用该 默认值,否则使用指定的实参。
全缺省参数:
举例void TestFunc (int a=10,int b=20,int c=30)。在进行函数调用传参的时候是这样TestFunc(1,2),那么在运行函数的时候,在函数体内部就是1,2,30,因为没有给出第三个参数,所以第三个参数采用默认值。
半缺省(缺省部分参数 ):
从右向左缺省并且必须是连续的(所以传参时,从左到右的传参),在定义函数的时候void TestFunc (int a,int b, int c=30),默认参数只能由右边开始给出,所以不能写成这样:void TestFunc (int a,int b = 20, int c),

函数重载:

函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的 形参列表(参数个数 或 类型 或 顺序)必须不同,常用来处理实现功能类似数据类型不同的问题。
为什么C++支持函数重载,C语言不支持呢?

首先我们先看一下C语言编译链接的几个过程,假如有三个文件 List.h List.c test.c(test.c包含头文件List.h)。 编译生成可执行程序 Test : gcc List.c test.c -o Test,会经过以下几个过程

预处理 ->头文件展开、宏替换,条件编译,去掉注释
编译 ->语法检查,生成汇编代码。
汇编 ->汇编代码生成二进制代码
链接 ->经过上边的三个过程,List.c 和 test.c分别生成了两个文件 List.o 和 test.o,而链接就是将这两个文件链接起来,生成最终的可执行文件Test。
假如test.c的内容如此下:

#include"List.h"
int main(){
    list_push_back(1);
    return 0;
}

List.h 中有 list_push_back的声明:void list_push_back(int);
List.c中list_push_back()的实现。
gcc在链接时,会通过函数名list_push_back去List.c中寻找list_push_back()的实现。如下图所示;
在这里插入图片描述

因为它是通过函数名去寻找的,所以c语言不支持函数名重载,因为如果有list_push_back同名,但参数不同的函数,寻找的时候就会有二义性,不知道这个函数名究竟对应哪个函数。而采用g++编译时会对函数名字增加修饰,编译器将函数参数类型信息添加到修改后的名字中,修改后的函数名 = 【_Z+函数长度+函数名+类型首字母】。链接时通过修饰后的函数名,去List.c文件中去找,就可以实现,函数名相同,参数不同的重载如下图:
在这里插入图片描述

引用:

引用概念:
引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。
(1)引用在定义时必须初始化
(2)一个变量可以有多个引用
(3)引用一旦引用一个实体,再不能引用其他实体
指针和引用的区别:
(1)指针是一个实体,需要分配内存空间,引用只是变量的别名,不需要分配内存空间.
(2)引用在定义的时候必须进行初始化,并且不能够改变(引用是针对已经在的某个单元格进行二次命名,所以单元格必须先存在)。指针在定义的时候不一定要初始化,并且指向的空间可变。不能有引用的值不能为NULL,而指针可以为nullptr。
(3)指针和引用的自增运算结果不一样。
(4)sizeof 引用得到的是所指向的变量(对象)的大小,而sizeof 指针得到的是指针本身的大小

内联函数:

以inline修饰的函数叫做内联函数,编译时C++编译器会调用内联函数的地方展开,没有函数压栈的开销,内联函数提升程序运行的效率。
☛. inline是一种以空间换时间的做法,省去调用函数额开销。所以代码很长或者有循环/递归的的函数不适宜使用内联。
☛. inline对于编译器而言只是一个建议,编译器会自动优化,如果定义为inline的函数体内有循环递归等等,编译器优化时会忽略掉内联。
☛. inline必须函数定义放在一起,才能成为内联函数,仅将inline放在声明前是不起不作用的。
☛. 定义在类内的成员函数默认定义为内联函数。
但是在一般的编译器下看不出内联函数的效果,因为编译器会自动优化。接下来给大家在linux下查看。

C++ 内存结构 BSS段,数据段,代码段,堆和栈

BSS段:通常是指用来存放程序中未初始化的全局变量和静态变量的一块内存区域。特点是可读写的,在程序执行之前BSS段会自动清0,所以,未初始的全局变量在程序执行之前已经成0了。

数据段:通常是指用来存放程序中已初始化的全局变量和静态变量的一块内存区域。数据段属于静态内存分配。

代码段:通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读(某些架构也允许代码段为可写,即允许修改程序)。
在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。

堆:堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。
当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);
当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)。

栈:又称堆栈,是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。
除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。

static全局变量与普通的全局变量有什么区别 ?
全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式。 这两者在存储方式上并无不同。
这两者的区别在于非静态全局变量的作用域是整个源程序, 当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用,因此可以避免在其它源文件中引起错误。
static局部变量和普通局部变量有什么区别 ?
把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。静态局部变量只能被其作用域内的变量和函数进行访问使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值