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作为关键字引入的,不需要包含头文件。
    在这里插入图片描述

🦀🦀观看~

相关内容

热门资讯

常用商务英语口语   商务英语是以适应职场生活的语言要求为目的,内容涉及到商务活动的方方面面。下面是小编收集的常用商务...
六年级上册英语第一单元练习题   一、根据要求写单词。  1.dry(反义词)__________________  2.writ...
复活节英文怎么说 复活节英文怎么说?复活节的英语翻译是什么?复活节:Easter;"Easter,anniversar...
2008年北京奥运会主题曲 2008年北京奥运会(第29届夏季奥林匹克运动会),2008年8月8日到2008年8月24日在中华人...
英语道歉信 英语道歉信15篇  在日常生活中,道歉信的使用频率越来越高,通过道歉信,我们可以更好地解释事情发生的...
六年级英语专题训练(连词成句... 六年级英语专题训练(连词成句30题)  1. have,playhouse,many,I,toy,i...
上班迟到情况说明英语   每个人都或多或少的迟到过那么几次,因为各种原因,可能生病,可能因为交通堵车,可能是因为天气冷,有...
小学英语教学论文 小学英语教学论文范文  引导语:英语教育一直都是每个家长所器重的,那么有关小学英语教学论文要怎么写呢...
英语口语学习必看的方法技巧 英语口语学习必看的方法技巧如何才能说流利的英语? 说外语时,我们主要应做到四件事:理解、回答、提问、...
四级英语作文选:Birth ... 四级英语作文范文选:Birth controlSince the Chinese Governmen...
金融专业英语面试自我介绍 金融专业英语面试自我介绍3篇  金融专业的学生面试时,面试官要求用英语做自我介绍该怎么说。下面是小编...
我的李老师走了四年级英语日记... 我的李老师走了四年级英语日记带翻译  我上了五个学期的小学却换了六任老师,李老师是带我们班最长的语文...
小学三年级英语日记带翻译捡玉... 小学三年级英语日记带翻译捡玉米  今天,我和妈妈去外婆家,外婆家有刚剥的`玉米棒上带有玉米籽,好大的...
七年级英语优秀教学设计 七年级英语优秀教学设计  作为一位兢兢业业的人民教师,常常要写一份优秀的教学设计,教学设计是把教学原...
我的英语老师作文 我的英语老师作文(通用21篇)  在日常生活或是工作学习中,大家都有写作文的经历,对作文很是熟悉吧,...
英语老师教学经验总结 英语老师教学经验总结(通用19篇)  总结是指社会团体、企业单位和个人对某一阶段的学习、工作或其完成...
初一英语暑假作业答案 初一英语暑假作业答案  英语练习一(基础训练)第一题1.D2.H3.E4.F5.I6.A7.J8.C...
大学生的英语演讲稿 大学生的英语演讲稿范文(精选10篇)  使用正确的写作思路书写演讲稿会更加事半功倍。在现实社会中,越...
VOA美国之音英语学习网址 VOA美国之音英语学习推荐网址 美国之音网站已经成为语言学习最重要的资源站点,在互联网上还有若干网站...
商务英语期末试卷 Part I Term Translation (20%)Section A: Translate ...