C++ 初阶 新语言入门介绍:命名空间,(全/半)缺省函数,函数重载,引用,内联,auto
Posted SuchABigBug
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++ 初阶 新语言入门介绍:命名空间,(全/半)缺省函数,函数重载,引用,内联,auto相关的知识,希望对你有一定的参考价值。
目录
一、C++介绍
C++语言发展最重要的两个版本里程碑:C++98和C++11
C++98: 是第一个C++标准版本,以模版方式重写C++标准款,引入了STL(标准模版库),简而言之语言比较完善
C++11: 增加了许多特性如:正则表达、基于范围for循环、auto关键字、新容器、列表初始化、标准线程库等
C++中的63个关键字
二、命名空间(namespace)
在C++中变量名、函数和后面学到的类都大量存在,这些名称在大型项目中可能存在冲突,所以就有了namespace这个关键词,目的是对标识符的名称进行本地化,从而避免命名冲突或名字污染
我们常用的using namespace std标准库,在预处理阶段会展开
下面自定义一个命名空间,里面既可以定义变量也可以定义函数
- 命名空间定义
- 命名空间嵌套
- 同一个工程中允许存在多个相同的命名空间,编译器最后合成一个命名空间
三、缺省参数(全缺/半缺)
缺省参数是声明或定义函数时为函数的参数指定一个默认值,调用该函数时,如果没有指定实参则采用该默认值,否则使用指定的实参
//全缺省
void TestFunc(int defaultVal=100, int defaultVal2=101, int defaultVal3=102)
cout << defaultVal << " " << defaultVal2 << " " << defaultVal3 << endl;
上面代码有三个参数,调用TestFunc函数,如果不指定实参那么会采用指定的默认值
//半缺省
void TestFunc2(int defaultVal, int defaultVal2, int defaultVal3=102)
cout << defaultVal << " " << defaultVal2 << " " << defaultVal3 << endl;
调用函数方式:
TestFunc(); //未指定实参
TestFunc2(10 , 11); //从左到往右依次传实参
四、函数重载
C++中允许同一作用域
中声明几个功能类似的同名函数
,这些同名函数的形参列别必须满足参数个数不同,或者类型,或者顺序不同,用来处理实际功能类似数据类型不同的问题
int Add(int a, int b)
return a+b;
//不同参数个数
int Add(int a, int b, int c)
return a+b+c;
//不同类型
double Add(double a, int b)
return a+b;
//调换顺序
int Add(int a, double b)
return a+b;
我们可以看到上面的代码函数名都是一样的,参数构成函数重载
那么为什么C语言中没有,而C++中支持函数重载呢?
这就需要从程序编译过程说起,编译分为预处理、编译、汇编、链接
在链接阶段,调用的函数会重定位符号表,我们通过objdump -S FuncReload
来查看C++的函数名经过了名字修饰(name Mangling)
gcc编译完后,函数名字的修饰没有发生改变,而g++编译器下,函数名字的修饰发生改变,编译器将函数参数类型信息添加到修改后的名字中
上图可以看到函数名都以__z3开头,函数名再接各参数类型的首字母。
因此只要参数不同,修饰出来的名字就不一样,也就支持了重载。
五、引用
引用是给已存在变量取了一个别名就好像你叫王二蛋,在家里蛋蛋这个别名永远在妈妈口中挂着
编译器不会为引用变量开辟内存空间,引用变量和被引用的变量共用一块内存空间,我们用符号&
表示
引用的符号为&,其使用方法是 类型 + & + 引用变量名称(对象名) = 引用实体; (引用实体的类型必须和&前的类型保持一致)
b变量对变量a进行引用,下图我们可以看到memory里面的地址都为同一个
int a = 10;
int& b = a;
1. 引用特征
1.引用在定义同时必须要初始化。比如在取别名的时候就需要有这个被取别名的对象。
2.一个引用实体可以有多个引用。
3.一旦引用变量成为了一个实体的引用,就不能再成为其他实体的引用。
int main()
int a = 10;
int d = 100;
//一旦写了引用,就必须有完整的实体,不能写成 int& b; 这是不允许的,即第一条特性
int& b = a;
//a变量被引用了两次,也就是第二条特性意思
int& c = a;
//前面c已经成了a的别名,那么c就永远只能是a的别名,只不过这里C的值变成了100(同样ab也变成100),特征三
c = d;
return 0;
2. 引用与指针有哪些区别?
(1)引用需要初始化,而指针没有要求。
(2)引用一旦作为一个引用实体的引用,就不能再作为其他实体的引用,但指针可以修改其所指向的对象的。
(3)引用没有独立空间,而指针有,但是引用的效率也会更高(毕竟少开辟了一大块内存空间)。
(4)对于sizeof,引用变量的大小与类型有关,指针变量的大小与类型无关。
(5)对于自加,引用加一是数值上加一,而指针加一是跳过一个类型的大小。
(6)访问实体的方式不同,指针是通过解引用访问,而引用是编译器自己处理。
(7)引用使用起来相对于指针更安全。
3. 引用使用场景
- 作为参数
(1)可以减少传参拷贝(引用作用)
truct node //某个结构体,假设很大
int val;
struct node* next;
;
//如果参数为引用,将不需要通过函数传递方式中的值传递(拷贝),提高效率
void modify(struct node& node0)
//此处省略...
(2)可以保护形参不被修改,既可以接收变量,又可以接收常量(常量引用作用).
int add(const int& a,const int& b)
// a = 15; //会报错,这样避免被修改
return a-b;
int main()
int a = 10;
int b = 20;
cout<<"变量作为实参"<<add(a,b)<<endl;
cout<<"常量作为实参"<<add(10,20)<<endl; //必须是常量引用,否则将无法接收实参
return 0;
- 作为返回值
六、内联
关键词:inline
以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数压栈的开销,内联函数提升程序运行的效率
如果在前面增加inline keyword将改成内联函数
这实际上是一种以空间换时间的做法,省去调用函数额外开销,因此代码太长或者循环递归函数不适宜作为内联函数。
不过也不用太担心,编译器会自动优化,如果函数体内有循环/递归等,编译器优化时会忽略掉内联
Warning:
inline不建议声明和定义分离,分离会导致链接错误,因为inline被展开,就没有函数地址了,那么链接就会找不到
七、auto
auto关键字是在C++2011年以后赋予的全新含义,作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期推导而得
Warning:
使用auto定义变量时必须对其进行初始化,因为编译器需要根据初始化表达式来推导auto的实际类型,因此auto并非是一种类型的声明,而是一个类型声明的占位符,编译器在编译期会将auto替换为变量实际的类型
int TestAuto()
return 10;
int main()
int a = 10;
auto b = a;
auto c = 'a';
auto d = TestAuto();
cout << typeid(b).name() << endl;
cout << typeid(c).name() << endl;
cout << typeid(d).name() << endl;
cout << typeid(d).name() << endl;
//auto e; <------会报错因为编译器推导不出来
还有不能推导的场景:
- auto不能作为函数的参数
- auto不能直接用来声明数组
void TestFor()
int array[] = 1, 2, 3, 4, 5 ;
for (int i = 0; i < sizeof(array) / sizeof(array[0]); ++i)
array[i] *= 2;
for (int* p = array; p < array + sizeof(array)/sizeof(array[0]); ++p)
cout << *p << endl;
上面为C++98中遍历一个数组的方式
下面是基于范围for的新用法,冒号的前面部分是范围内用于迭代的变量,第二部分表示被迭代的范围
void TestFor()
int array[] = 1, 2, 3, 4, 5 ;
for(auto& e : array)
e *= 2;
for(auto e : array)
cout << e << " ";
return 0;
创作不易,如果文章对你帮助的话,最后的最后点赞哦:)
以上是关于C++ 初阶 新语言入门介绍:命名空间,(全/半)缺省函数,函数重载,引用,内联,auto的主要内容,如果未能解决你的问题,请参考以下文章