一.引言
当我们有一定的C语言基础,再去学习另一(C++)相对来说便会容易很多,而要学习一门新的语言,首先我们就要学习他的语法,而且每一门语言都有其独特的优势,我们的·C++祖师爷也正因为C语言的一些不便之处将其以更方便的形式在C++中所实现,下面让我带大家一起从C语言过度到C++,走进C++的世界。
二.C++发展史与重要意义
2.1C++的发展历史
C++的起源可以追溯到1979年,当时BjarneStroustrup(本贾尼·斯特劳斯特卢普,这个翻译的名字不 同的地⽅可能有差异)在⻉尔实验室从事计算机科学和软件⼯程的研究⼯作。⾯对项⽬中复杂的软件开 发任务,特别是模拟和操作系统的开发⼯作,他感受到了现有语⾔(如C语⾔)在表达能⼒、可维护性 和可扩展性⽅⾯的不⾜。 1983年,BjarneStroustrup在C语⾔的基础上添加了⾯向对象编程的特性,设计出了C++语⾔的雏形, 此时的C++已经有了类、封装、继承等核⼼概念,为后来的⾯向对象编程奠定了基础。这⼀年该语⾔被 正式命名为C++。 在随后的⼏年中,C++在学术界和⼯业界的应⽤逐渐增多。⼀些⼤学和研究所开始将C++作为教学和研 究的⾸选语⾔,⽽⼀些公司也开始在产品开发中尝试使⽤C++。这⼀时期,C++的标准库和模板等特性 也得到了进⼀步的完善和发展。 C++的标准化⼯作于1989年开始,并成⽴了⼀个ANSI和ISO(InternationalStandards Organization)国际标准化组织的联合标准化委员会。1994年标准化委员会提出了第⼀个标准化草 案。在该草案中,委员会在保持斯特劳斯特卢普最初定义的所有特征的同时,还增加了部分新特征。 在完成C++标准化的第⼀个草案后不久,STL(StandardTemplateLibrary)是惠普实验室开发的⼀系 列软件的统称。它是由AlexanderStepanov、MengLee和DavidRMusser在惠普实验室⼯作时所开发 出来的。在通过了标准化第⼀个草案之后,联合标准化委员会投票并通过了将STL包含到C++标准中的 提议。STL对C++的扩展超出C++的最初定义范围。虽然在标准中增加STL是个很重要的决定,但也因 此延缓了C++标准化的进程。 1997年11⽉14⽇,联合标准化委员会通过了该标准的最终草案。1998年,C++的ANSI/IS0标准被投⼊ 使⽤。
2.2C++的版本更新
2.3C++的重要性
截止至2024年一月,C++在TIOBE编程语言社区一直稳居前三的位置。虽然语言排名并不能衡量一种语言的优劣,但是一门受众广的语言自然有良好的发展前景。
2.4C++就业前景与方向
在这里我就不详细的介绍了,只简单讲述一下大致方向
1. ⼤型系统软件开发。
2. ⾳视频处理。
3. PC客⼾端开发。
4. 服务端开发。
5. 游戏引擎开发。
6. 嵌⼊式开发。
7. 测试开发/测试。
三.走进C++的世界
这篇文章我们首先会着重介绍一些C++根据C语言的一些不方便之处所优化出的一些方法,因为C++是兼容C语言的所以不必太过纠结C++的语法先
3.1第一个C++程序
#include<iostream>
using namespcae std
int main()
{
cout << "hello world\n" << endl;
return 0;
}
C++有自己的一套输入输出,看不懂没关系,下面我们会一一介绍
3.2命名空间
• 定义命名空间,需要使⽤到namespace关键字,后⾯跟命名空间的名字,然后接⼀对{}即可,{}中 即为命名空间的成员。命名空间中可以定义变量/函数/类型等。
• namespace本质是定义出⼀个域,这个域跟全局域各⾃独⽴,不同的域可以定义同名变量,所以下 ⾯的rand不在冲突了。
• C++中域有函数局部域,全局域,命名空间域,类域;域影响的是编译时语法查找⼀个变量/函数/ 类型出处(声明或定义)的逻辑,所有有了域隔离,名字冲突就解决了。局部域和全局域除了会影响 编译查找逻辑,还会影响变量的⽣命周期,命名空间域和类域不影响变量⽣命周期。
• namespace只能定义在全局,当然他还可以嵌套定义。
• 项⽬⼯程中多⽂件中定义的同名namespace会认为是⼀个namespace,不会冲突。
• C++标准库都放在⼀个叫std(standard)的命名空间中。
3.2.1定义命名空间
#include<iostream>
#include<stdlib.h>
namespace xingxing
{
int rand = 1;
}
int main()
{
printf("%d\n", xingxing::rand);
//使用域作用限定符,指定作用域
return 0;
}
想要使用我们所定义的命名空间我们就要使用域作用限定符“::”如果未指定命名空间,编译器将报错。
3.2.2using的使用
在我们书写代码时,可能会频繁调用某个函数,这是我们可以使用using部分展开,来简化代码。使用方式为using 命名空间名称:: 成员。
下面我们区分一下部分展开和全部展开
//部分展开
#include<iostream>
using std::cout;
using std::endl;
int main()
{
cout << "hello xingxing" << endl;
cout << "hello xingxing" << endl;
cout << "hello xingxing" << endl;
return 0;
}
//全部展开
#include<iostream>
using namespace std;
int main()
{
cout << "hello xingxing" << endl;
cout << "hello xingxing" << endl;
cout << "hello xingxing" << endl;
return 0;
}
3.2.3命名空间的嵌套与合并
#include<iostream>
using namespace std;
namespace littlepigwithtwoguns
{
int cs = 2;
namespace xingxing
{
int csgo = 1;
}
}
int main()
{
cout << littlepigwithtwoguns::cs << endl;
cout << littlepigwithtwoguns::xingxing::csgo << endl;
return 0;
}
namespace xingxing
{
int a = 1;
}
namespace xingxing
{
int b = 1;
}
//编译时会自动合并
3.3输入输出
C++的标准输入与输出函数是cin与cout,分别对应C语言的printf与scanf。但是相较于C语言,C++输入输出并不需要指定占位符,如:%d,%c等。
在C++中使用cin与cout,需要包含头文件iostream以及std标准命名空间。
3.4缺省参数
• 缺省参数是声明或定义函数时为函数的参数指定⼀个缺省值。在调⽤该函数时,如果没有指定实参 则采⽤该形参的缺省值,否则使⽤指定的实参,缺省参数分为全缺省和半缺省参数。(有些地⽅把 缺省参数也叫默认参数)
• 全缺省就是全部形参给缺省值,半缺省就是部分形参给缺省值。C++规定半缺省参数必须从右往左 依次连续缺省,不能间隔跳跃给缺省值。
• 带缺省参数的函数调⽤,C++规定必须从左到右依次给实参,不能跳跃给实参。
• 函数声明和定义分离时,缺省参数不能在函数声明和定义中同时出现,规定必须函数声明给缺省 值。
3.5函数重载
C++⽀持在同⼀作⽤域中出现同名函数,但是要求这些同名函数的形参不同,可以是参数个数不同或者 类型不同。这样C++函数调⽤就表现出了多态⾏为,使⽤更灵活。C语⾔是不⽀持同⼀作⽤域中出现同 名函数的。
3.6内联函数
• ⽤inline修饰的函数叫做内联函数,编译时C++编译器会在调⽤的地⽅展开内联函数,这样调⽤内联 函数就不需要建⽴栈帧了,就可以提⾼效率。
• inline对于编译器⽽⾔只是⼀个建议,也就是说,你加了inline编译器也可以选择在调⽤的地⽅不展 开,不同编译器关于inline什么情况展开各不相同,因为C++标准没有规定这个。inline适⽤于频繁 调⽤的短⼩函数,对于递归函数,代码相对多⼀些的函数,加上inline也会被编译器忽略。
• C语⾔实现宏函数也会在预处理时替换展开,但是宏函数实现很复杂很容易出错的,且不⽅便调 试,C++设计了inline⽬的就是替代C的宏函数。
3.7nullptr
C++中NULL可能被定义为字⾯常量0,或者C中被定义为⽆类型指针(void*)的常量。不论采取何种 定义,在使⽤空值的指针时,都不可避免的会遇到⼀些⿇烦,本想通过f(NULL)调⽤指针版本的 f(int*)函数,但是由于NULL被定义成0,调⽤了f(intx),因此与程序的初衷相悖。f((void*)NULL); 调⽤会报错。
C++11中引⼊nullptr,nullptr是⼀个特殊的关键字,nullptr是⼀种特殊类型的字⾯量,它可以转换 成任意其他类型的指针类型。使⽤nullptr定义空指针可以避免类型转换的问题,因为nullptr只能被 隐式地转换为指针类型,⽽不能被转换为整数类型。
3.8引用
3.8.1引用的概念和定义
引⽤不是新定义⼀个变量,⽽是给已存在变量取了⼀个别名,编译器不会为引⽤变量开辟内存空间, 它和它引⽤的变量共⽤同⼀块内存空间。
3.8.2引用的特性
• 引⽤在定义时必须初始化
• ⼀个变量可以有多个引⽤
• 引⽤⼀旦引⽤⼀个实体,再不能引⽤其他实体
3.8.3引用的使用
• 引⽤在实践中主要是于引⽤传参和引⽤做返回值中减少拷⻉提⾼效率和改变引⽤对象时同时改变被 引⽤对象。
• 引⽤传参跟指针传参功能是类似的,引⽤传参相对更⽅便⼀些。
• 引⽤返回值的场景相对⽐较复杂,我们在这⾥简单讲了⼀下场景,还有⼀些内容后续类和对象章节 中会继续深⼊讲解。
• 引⽤和指针在实践中相辅相成,功能有重叠性,但是各有特点,互相不可替代。C++的引⽤跟其他 语⾔的引⽤(如Java)是有很⼤的区别的,除了⽤法,最⼤的点,C++引⽤定义后不能改变指向, Java的引⽤可以改变指向。
• ⼀些主要⽤C代码实现版本数据结构教材中,使⽤C++引⽤替代指针传参,⽬的是简化程序,避开 复杂的指针,但是很多同学没学过引⽤,导致⼀头雾⽔。
3.8.4引用和指针的区别与关系
C++中指针和引⽤就像两个性格迥异的亲兄弟,指针是哥哥,引⽤是弟弟,在实践中他们相辅相成,功 能有重叠性,但是各有⾃⼰的特点,互相不可替代。
• 语法概念上引⽤是⼀个变量的取别名不开空间,指针是存储⼀个变量地址,要开空间。
• 引⽤在定义时必须初始化,指针建议初始化,但是语法上不是必须的。
• 引⽤在初始化时引⽤⼀个对象后,就不能再引⽤其他对象;⽽指针可以在不断地改变指向对象。
• 引⽤可以直接访问指向对象,指针需要解引⽤才是访问指向对象。
• sizeof中含义不同,引⽤结果为引⽤类型的⼤⼩,但指针始终是地址空间所占字节个数(32位平台下 占4个字节,64位下是8byte)
• 指针很容易出现空指针和野指针的问题,引⽤很少出现,引⽤使⽤起来相对更安全⼀些。
四.结语
本篇文章给大家介绍了一些C++一些基础的语法以及不同于C语言的地方,准确来说是我们的本贾尼博士根据C语言一些不方便的点,有针对性的添加的一些优化,随着我们深入地学习,便会越来越感受到其中的方便之处
本章我们并没有做太多的代码演示,随着我们学习的深入,将会对上面的内容深入理解与使用。