C++ 入门篇
创始人
2024-06-02 08:34:25
0

目录

    • 一. 命名空间
      • 1. 介绍
      • 2. 定义命名空间
      • 3. 使用
      • 4. cin与cout
    • 二. 缺省参数
      • 1. 介绍
      • 2. 全缺省参数
      • 3. 半缺省参数
      • 4. 其他
    • 三. 函数重载
      • 1. 介绍
      • 2. 使用
      • 3. name Mangling(名字修饰)
      • 4. extern "C"
    • 四. 引用
      • 1. 介绍
      • 2.特点
      • 3.常引用
      • 4.使用
      • 5.引用与指针
    • 五. inline函数
      • 1. 介绍
      • 2. 特性
    • 六. auto
      • 1. 介绍
      • 2. 细节
    • 七.范围for循环
      • 1.介绍
      • 2. 使用
    • 八.空指针
      • 1. NULL
      • 2.nullptr

从c语言进阶到c++的必备基础知识

一. 命名空间

1. 介绍

对于类、函数或变量的在同一作用域中时,可能会因为相同标识符冲突。因此使用命名空间的目的是:对标识符的名称进行本地化,避免命名冲突或名字污染

2. 定义命名空间

定义一个命名空间,就定义了一个作用域,命名空间中的内容都局限于该命名空间

使用关键字:namespace

//1.普通命名空间
namespace N1//N1是命名空间的名称
{static int times = 0;int add(int n1, int n2){return n1 + n2;}
}//2.嵌套的命名空间
namespace N2
{int sub(int n1, int n2){return n1 - n2;}namespace N3{int sub(int n1, int n2){return abs(n1 -n2);}}
}//3. 同名命名空间
//同一个项目中的多个同名命名空间,在编译的时候
//会合并为同一个命名空间
namespace N1
{int sub(int n1, int n2){return n1 - n2;}
}

3. 使用

以上述的三个命名空间举例,命名空间的使用主要有三种方式:

//1.使用其中某个函数、变量或类时,
//前面加 命名空间名 和 作用域限定符
int main()
{printf("%d\n", N1::times);int ret1 = N2::sub(1, 9);int ret2 = N2::N3::sub(1, 9);return 0;
}
//2. 使用using引入命名空间中成员
using N1::times;//sub函数会发生命名冲突
//using N2::sub;
//using N2::N3::sub;int main()
{printf("%d\n",times);//int ret1 = sub(1, 9);//int ret2 = sub(1, 9);return 0;
}
//3. using namespace + 命名空间 
using namespace N1;
int main()
{printf("%d\n",times);int ret1 = add(1, 1);int ret2 = sub(1, 1);return 0;
}

对于方法3,因为会将命名空间的内容全部展开(就相当于放在全局域中),就无法起到它的作用了。因此,在实际项目中建议使用方法2展开常用的,能更好的避免命名冲突。

4. cin与cout

#include int main()
{int a;double b;char c;std::cin >> a >> b >> c;std::cout << "---------\n";std::cout << " a = " << a;std::cout << " b = " << b;std::cout << " c = " << c << std::endl;return 0;
}

在这里插入图片描述

其中cin 不会记录空格和换行符,cout会自动识别类型,endl的作用相当于\n


二. 缺省参数

1. 介绍

在声明或定义函数时,为其参数指定默认值。则可以在没有实参的情况下,使用该的默认值。

int add(int a = 0, int b = 0)
{return a + b;
}
int main()
{add();   //没有传参,会使用默认值add(1, 1);//传入实参 1,1return 0;
}

2. 全缺省参数

int add(int a = 0, int b = 0, int c = 0)
{return a + b + c;
}
int main()
{add();		 // a=0,b=0,c=0add(1);	     // a=1,b=0,c=0add(1, 2);   //a=1,b=2,c=0add(1, 2, 3);//a=1,b=2,c=3return 0;
}

3. 半缺省参数

int add(int a , int b = 0, int c = 0)
{return a + b + c;
}
int main()
{//add();// a不是缺省参数所有必须传参add(1);	     // a=1,b=0,c=0add(1, 2);   //a=1,b=2,c=0add(1, 2, 3);//a=1,b=2,c=3return 0;
}

函数的参数列表中,半缺省参数必须从右→左依次定义没有默认值的参数,不能间隔

4. 其他

函数的定义和声明不能同时出现缺省参数
在这里插入图片描述
同时使用默认参数时,如果给定的默认值不同也会造成冲突。

因此只用在声明或定义时使用缺省参数。

int add(int a , int b = 0, int c = 0);int add(int a, int b, int c )
{return a + b + c;
}

缺省值必须是常量或者全局变量


三. 函数重载

1. 介绍

c++允许在同一作用域下,有多个参数列表不同,函数名相同的函数,称为函数重载,用于处理数据类型不同但是功能相似的问题。

2. 使用

#include using namespace std;int Add(int n1, int n2)
{return n1 + n2;
}
double Add(double n1, double n2)
{return n1 + n2;
}int main()
{int a = 1;double b = 1;cout << Add(a, a) << endl;cout << Add(b, b) << endl;return 0;
}

调用函数时,会根据参数类型自动匹配到对应的函数。

3. name Mangling(名字修饰)

c语言不能支持函数重载,如果想要实现上述函数,只能命名如Add1(),Add2(),来区分不同函数。

那么为什么C++可以支持函数重载呢?

从写好的.cpp———>可以运行的 .exe文件,需要经历预处理,编译,汇编,链接几个过程。

在链接阶段,链接器会将调用的Add的地址找到,然后链接起来,其中链接器也是通过名字去找到的,而且不同编译器对函数名都有自己的修饰规则。

因为Linux下gcc/g++对函数的命名规则比较简单,以下示例:
在这里插入图片描述

test.c文件,经过c语言编译器gcc编译后,我们可以发现其汇编语言中,调用的分别对应Add()——< Add >,Sub()——< Sub >


在这里插入图片描述
test.cpp文件,经过c++编译器g++编译后,其汇编语言中g++将函数名修饰后变成**{_Z+函数名长度+函数名+参数类型首字母}**

由此可以看出,是因为c++的编译器会对函数名进行修饰,因此可以支持函数重载。

值得一提的是,返回值不同不是函数重载的要素。

4. extern “C”

​ 由于c和c++编译器对函数名的修饰规则不同,因此c++中调用c语言实现的静态库或者动态库时会出现问题。因此就需要在函数前加extern “C”,来告诉编译器,将该函数按照c语言的规则来编译。

参考链接:创建与使用静态库
在这里插入图片描述

在c++程序中,包含Add.h后,经过extern "C"修饰,就可以成功使用c语言的静态库了。

四. 引用

1. 介绍

  • 语法:类型& 引用名 = 引用实体;

    相当于给一个已经存在的变量,起一个别名,可以通过这个引用名访问到该变量本身
    在这里插入图片描述

2.特点

  • 引用类型必须和引用实体是同种类型
  • 引用在定义时必须初始化
  • 一个变量可以有多个引用,但是一个引用只能有一个实体,且不能再更改。

3.常引用

  • 对于const修饰的变量,需要使用const修饰的引用,即为常引用
  • 若常引用和实体是不同的基本类型,常引用所引用的实际上是实体的拷贝
    在这里插入图片描述

常量a 需要常引用c 来引用

d作为int型的常引用来引用double型的变量b,是因为常引用d实际上引用的是b转换为int型的拷贝(地址不同)

4.使用

  • 通常使用引用做返回值或参数时,主要因为其类似于指针,即可以节省空间又可以节省时间
  1. 参数
void Swap(int& a, int& b)
{int temp = a;a = b;b = temp;
}

a,b都是引用类型,因此在Swap内的交换可以改变其引用的实体

适用场景:输出行参数(如上例),大对象传参

  1. 返回值
int& Add(int a, int b)
{static int sum = a+b;return sum;
}

由于sum是静态变量,因此其作用域为全局,可以返回其引用。

适用场景:修改返回对象,大对象返回

下例为一个错误示范 :
在这里插入图片描述

由于调用完Add()函数后不久,系统会回收其所占用的栈空间,其中就包括sum,因此对于a最后会变成随机值。

5.引用与指针

在语法概念上引用就是一个别名,和其引用实体共用一块空间;指针有固定大小的空间(4/8),存放的是所指向空间的首地址

在底层实现中,引用实际有自己的空间,因为引用是按照指针的方式来实现的。
在这里插入图片描述

如图,指针和引用的操作,其汇编代码相同

不同点:

1.引用在定义时必须初始化,指针无此要求

2.引用不能再更改为其它引用实体,指针可以指向任意同类型实体

3.没有NULL的引用,有NULL的指针

4.在sizeof下含义不同,引用结果为引用类型的大小,指针结果为自身(地址空间,32位平台下占4个字节)的大小

5.引用++即实体增1,指针++即指针指向向后偏移一个类型的大小

6.没有多级引用,有多级指针

7.访问实体时,引用时编译器会自动处理,指针需要显示解引用

8.引用比指针使用更安全

五. inline函数

1. 介绍

​ 以inline修饰的函数叫做内联函数。编译时,编译器会在调用内联函数的地方将函数展开,来减少函数调用所建立和销毁栈帧的开销,提高程序的运行效率。
在这里插入图片描述
在这里插入图片描述

当使用inline后,可以看见没有调用函数call了,而是直接执行函数的语句。


c语言中,对于类似问题的解决,提供宏函数来提高效率#define Add(a+b) ((a)+(b))

宏的优点:1.复用性强 2.提高效率

宏的缺点:1.可读性差 2.没有类型安全检查 3.不方便调试(因为预处理阶段进行了替换)

C++中基本不再建议使用宏,尽量使用const、enum、inline来代替宏

2. 特性

  • 内联函数是一种以空间换时间的做法,会用函数体来替换函数调用,多次调用,会使目标文件变大(参考上图所示)。因此代码很长 或者 递归的函数不适用
  • inline对于编译器而言只是一个建议,编译器会自动优化。一般将函数规模较小、不是递归、频繁调用的函数,采用inline修饰,否则会忽略inline特性。
  • 内联函数不建议定义和声明分离(分别放在.cpp与.h,对于使用该函数的其他.cpp文件,因为是单独编译的,所有是找不到函数体的。)

六. auto

1. 介绍

auto的作用是自动推导类型,用于解决类型难拼写、类型不明确
在这里插入图片描述

使用auto定义变量时,必须初始化。编译时编译器根据初始化表达式来推导auto的实际类型,将auto替换为变量实际的类型。因此auto是声明类型时的"占位符"。

2. 细节

  1. 指针与引用

    用auto声明指针类型时,使用autoauto*没有区别,但是声明引用类型 时必须加&
    在这里插入图片描述

  2. 同一行定义多个变量

当在一行声明多个变量时,这些变量必须是相同的类型。因为编译器实际只对第一个类型进行推导,然后根据推导出来的类型定义其他的变量。

auto a = 1, b = 2, c = 3;

  1. auto不能作为函数的参数

    编译阶段无法推导实际类型

  2. auto不能直接声明数组

七.范围for循环

1.介绍

对于有范围的集合的整体遍历,可以不用像for(;;)来说明循环的范围。

int a[] = { 1,2,3,4,5 };
for (int t : a)
{cout << t << " ";
}

for()内用:来分隔成两部分,int t表示用于迭代的变量,a表示被迭代的范围。

循环从开始到结束,会依次取数组a的值赋值给局部变量t,然后输出。

2. 使用

  1. auto
int a[] = { 1,2,3,4,5 };
for (auto t : a)
{cout << t << " ";
}

当不清楚集合a的类型时,可以直接使用auto来推导

  1. 引用
int a[] = { 1,2,3,4,5 };
for (auto& t : a)
{t++;cout << t << " ";
}

使用引用后,t就是a元素的别名,因此可以通过t来改变a中元素的内容

  1. 和普通循环一样,也可以使用continue,break
  2. 底层实际上是迭代器,需要确定范围的begin和end
//void test(int a[])
//{
//	for (auot& t : a)
//	{
//		cout << t << " ";
//	}
//}

对于上例中,函数参数a接收的是一个指针,因此数组的范围不能明确,会报错。

八.空指针

1. NULL

在c语言里,我们使用的是NULL来表示空指针。NULL实际上是一个宏,底层实现下:

#ifndef NULL#ifdef __cplusplus#define NULL 0#else#define NULL ((void *)0)#endif
#endif

因此NULL可能被定义为字面常量0或者是无类型指针(void*)的常量,而字面常量0,编译器默认看作为整型常量。

因此会出现下例问题:
在这里插入图片描述

语法中NULL应该表示空值指针,程序却没有调用fun(int* a),相悖 。

2.nullptr

建议使用nullptr来表示空指针。

  • nullptr是c++11作为关键字引入的,不需要包含头文件。
    在这里插入图片描述

🦀🦀观看~

相关内容

热门资讯

我发现了生活中的美小学三年级... 我发现了生活中的美 小学三年级作文 篇一今天,在我走进学校的大门时,我发现了生活中的美。我望着校园的...
猜猜我是谁200字三年级作文... 猜猜我是谁200字三年级作文 篇一假如我是一只小鱼,你能猜到吗?我住在水里,每天游来游去,不用担心吃...
我的正能量书信大赛征文四年级... 我的正能量书信大赛征文四年级 篇一亲爱的老师:您好!我是你们班的学生小明。我写这封信是为了向您分享一...
真情常在四年级作文【通用3篇... 真情常在四年级作文 篇一我的好朋友真情常在,这是我在四年级学习生活中最深刻的感受。我有一个好朋友,她...
一处美丽的自然景观作文四年级... 一处美丽的自然景观作文四年级85篇 篇一大自然给人类带来了无尽的美景,其中有一处我觉得最美丽的自然景...
关于描写妈妈的作文400字四... 关于描写妈妈的作文400字四年级 篇一妈妈是我最敬爱的人,她是一个温柔而又坚强的女人。她总是默默地为...
四年级作文小小动物园600字... 四年级作文小小动物园600字 篇一小小动物园的一天今天,我和同学们来到了小小动物园,我们都非常兴奋。...
春天来了四年级作文300字【... 春天来了四年级作文300字 篇一春天的脚步渐渐地临近了,大地一片生机勃勃。我喜欢春天,因为春天里有温...
我的心愿四年级100字作文怎... 篇一:我的心愿四年级100字作文怎么写42篇第一篇内容:我希望成为一名优秀的画家我是一个喜欢画画的孩...
感动的事四年级作文300字【... 感动的事四年级作文300字 篇一我的小伙伴我有一个特别好的小伙伴,他叫小明。他是一个非常善良和乐于助...
回乡偶书【优选4篇】 回乡偶书 篇一 回乡偶书 篇二回乡偶书 篇三 重庆市忠县实验小学四年级二班:申晓航         ...
想象四年级作文400字(精简... 想象四年级作文400字 篇一我的未来世界我是一位四年级的学生,我有一个梦想,那就是拥有一个充满科技和...
四年级作文【精彩6篇】 四年级作文 篇一我喜欢的动物我喜欢的动物是小狗。小狗是一种可爱的动物,它们有着憨态可掬的外表和忠诚的...
四年级描写北京故宫的作文40... 四年级描写北京故宫的作文400字 篇一北京故宫是我国古代宫殿建筑的代表之一,它位于北京市中心,是中国...
四年级作文我的暑生活(通用6... 四年级作文我的暑生活 篇一我的暑假生活充满了欢乐和收获。这个暑假,我参加了许多有趣的活动,学到了很多...
玫瑰花和小雨珠四年级作文【通... 玫瑰花和小雨珠四年级作文 篇一玫瑰花和小雨珠我有一个好朋友,她叫小雨珠。她是我们班的班花,而我则是班...
我我快乐300字四年级作文8... 我快乐300字四年级作文 篇一我快乐的一天今天是我快乐的一天。早上我起床后,妈妈给我做了我最喜欢吃的...
我们这美丽的校园四年级作文(... 我们这美丽的校园四年级作文 篇一我热爱我的校园,因为它是如此美丽。每天早上,当我走进校园时,我都被各...
古老而神秘的海神庙四年级作文... 古老而神秘的海神庙四年级作文 篇一海神庙是一座古老而神秘的庙宇,位于一个小岛上。我和我的家人去参观了...
小书迷四年级作文【推荐6篇】 小书迷四年级作文 篇一看见书,我就忍不住心里狂喜。那是一种浓郁的书香,让我仿佛置身于一个神奇的世界。...