目录
一. C++的发展
为什么诞生
C++的起源可以追溯到1979年,当时Bjarne Stroustrup(本贾尼·斯特劳斯特卢普,)在⻉尔实验室从事计算机科学和软件⼯程的研究⼯作。⾯对项⽬中复杂的软件开发任务,特别是模拟和操作系统的开发⼯作,他感受到了现有语⾔(如C语⾔)在表达能⼒、可维护性和可扩展性⽅⾯的不⾜。
比较c语言的变化
C++支持类和对象的概念,使得代码更加模块化和可重用。
C++引入了模板,可以实现通用的函数和类,提高了代码的重用性和灵活性。
C++提供了更好的类型检查和错误处理机制,减少了代码中的错误和漏洞。
C++对内存管理和多线程编程进行了优化,提高了程序的执行效率和性能。
总的来说,C++较C语言提高了开发效率和代码的可维护性。
版本迭代
1. C++98 (C++95)
这是第一个正式的C++标准,由ISO于1998年发布。这个版本定义了C++的基本语法和特性,包括类、对象、模板、异常处理、输入输出流等。2. C++03
这是一个小修订版,主要修正了一些错误并增加了对标准库的一些细节说明。3. C++11 (C++0x)
发布于2011年,带来了许多重要的新特性,包括自动类型推断(auto),范围for循环,lambda表达式,智能指针,基于范围的for循环等。4. C++14
在C++11的基础上进行了一些小的改进和调整,例如对lambda表达式的改进和对constexpr函数的支持。5. C++17
引入了许多新特性,如结构化绑定、类模板参数推导、类模板中的inline变量、constexpr if语句、字符串视图、函数指针适配器等。6. C++20
发布于2020年,这是自C++17以来的一次重大更新,引入了模块(Modules),协程(Coroutines),范围for(Range-based for)的改进,等等。
应用领域
游戏、设备驱动程序、HPC(高性能计算)、云、桌面、嵌入式和移动应用等。
二. 命名空间
1. 为什么要使用命名空间
在c/c++中,变量、函数和后面要学到的类都是大量存在的,这些变量,函数和类的名称将都存在于全局作用域中,可能导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突和名字污染
2. 域
c++中域有:函数域,全局域,命名空间域,类域;
域影响的是编译时语法查找一个变量\函数类型出处(声明或定义)的一个逻辑,所以有了域隔离,名字冲突的问题就解决了。局部域和全局域除了会影响编译和查找逻辑,还会影响变量的生命周期,命名空间域和类域不影响变量的生命周期
可以通过域作用限定符来访问全局变量
演示代码如下
#include<iostream>
using namespace std;
int n=1111;
int main()
{
int n = 111;
// ::域作用限定符
printf("%d\n",::n);
printf("%d\n",n);
}
3. 命名空间的定义
定义命名空间需要用到namespace的关键字,后面跟命名空间的名字,然后接一对 { } 即可。{} 中即为命名空间的成员。命名空间中可以定义 变量、函数类型等
如下代码所示
namespace bbb
{
int n = 11;
int c = 666;
int s = 3;
int a = 2;
int ss(int n)
{
return 2 * n;
}
}
namespace的本质是定义一个域,这个域跟全局域各自独立,不同的域可定义同名变量
namespace只能定义在全局,还可以嵌套定义。
项目工程中多文件定义的同名namespace会认为是一个namespace,不会造成冲突。
可以通过域作用限定符来访问命名空间里的变量
演示代码如下
#include<iostream>
using namespace std;
int n=1111;
namespace bb
{
int n = 10;
namespace b//可以嵌套定义
{
int n = 1;
}
}
namespace bb//同名会自动合并
{
int s = 0;
}
namespace bbb
{
int n = 11;
int c = 666;
int s = 3;
int a = 2;
int ss(int S)
{
return 2 * S;
}
}
int main()
{
int n = 111;
// ::域作用限定符
printf("%d\n",::n);
printf("%d\n",bb::n);
printf("%d\n",bb::b::n);
printf("%d\n",bbb::n );
printf("%d\n",n);
printf("%d\n", bbb::ss(2));
}
4. 命名空间的使用
编译查找一个变量的声明或定义时,默认只会在局部或全局中查找,不会到命名空间里去查找。使用命名空间的定义的变量或函数有以下三种方式
1. 指定命名空间访问
即通过域作用限定符来访问
#include<iostream>
namespace pc
{
int a = 10;
int b = 20;
int c = 30;
}
int main()
{
printf("%d\n", pc::a);
return 0;
}
2. 利用using关键字将命名空间中某个成员展开
项目中经常访问的不存在冲突的成员推荐这种方式
#include<iostream>
namespace pc
{
int a = 10;
int b = 20;
int c = 30;
}
using pc::b;
int main()
{
printf("%d\n", b);
return 0;
}
我们通过using 展开了pc中的b并没有展开其他成员,所以如果调用其他成员还是会报错
3. 展开命名空间中的全部成员
项目不推荐使用,冲突风险很大,我们平时的一些小练习推荐使用
#include<iostream>
namespace pc
{
int a = 10;
int b = 20;
int c = 30;
}
using namespace pc;
int main()
{
printf("%d\n",a);
printf("%d\n", b);
printf("%d\n", c);
}
三. C++的输入和输出简要介绍
<iostream>是Input Output Stream的缩写,是标准的输入、输出流库,定义了标准的输入、输出对象。
C++标准库都放在一个叫std(standard)的命名空间中,所以前面需要使用域作用限定符,用命名空间的使用方式来使用它们
std::cout 是ostream类的对象,它主要面向窄字符的标准输出流。
std::cin 是istream类的对象,他主要面向窄字符的标准输入流。
std:: endl 是一个函数,流插入输出时,相当于一个换行字符加刷新缓冲区。
使用C++输入输出会更方便,不需要像printf/scanf输入输出一样还得用手动指定格式,C++的输入输出可以自动识别变量类型(其本质是通过函数重载实现的,下文会提到)。最重要的是C++的流能更好的支持自定义类型对象的输入输出。
#include<iostream>
int main()
{
int s;
std::cin >> s;
std::cout << s<<std::endl;
return 0;
}
由于IO流涉及很多后面的只是,所以这里不深入介绍C++IO流的用法
一般练习中我们可以使用using namespace std;来将标准库全部展开,实际项⽬开发中不建议using namespace std。
代码如下
#include<iostream>
using namespace std;
int main()
{
int s;
cin >> s;
cout << s<<endl;
return 0;
}
另外在vs中
没有包含<stdio.h>也可以使用printf与scanf,但是其他编译器可能会报错
如下代码在vs中不会报错
#include<iostream>
using namespace std;
int main()
{
int s;
scanf("%d", &s);
printf("111");
return 0;
}
四. 缺省参数
1. 概念
缺省参数是声明或定义函数时为函数的参数指定⼀个缺省值。在调⽤该函数时,如果没有指定实参 则采⽤该形参的缺省值,否则使⽤指定的实参,缺省参数分为全缺省和半缺省参数。(有些地⽅把 缺省参数也叫默认参数)
2. 实现
如下代码
#include<iostream>
using namespace std;
void test1(int a=10)//全缺省
{
printf("%d\n", a);
}
void test2(int a, int b = 111)//半缺省
{
cout << a <<" " << b << endl;
}
int main()
{
test1();
test1(666);
test2(1);
test2(22, 222);
return 0;
}
其中函数test1为全缺省,test2为半缺省
全缺省就是全部形参给缺省值,半缺省就是部分形参给缺省值。C++规定半缺省参数必须从右往左 依次连续缺省,不能间隔跳跃给缺省值。
3. 注意事项
带缺省参数的函数调⽤,C++规定必须从左到右依次给实参,不能跳跃给实参。
如下代码所示
#include<iostream>
using namespace std;
void test2(int a, int b = 111)
{
cout << a <<" " << b << endl;
}
void test3(int b = 111, int a)
{
cout << b << " " << a << endl;
}
int main()
{
test2(1);
test2(22, 222);
test3(1);
return 0;
}
我们发现test3(1);的调用会出错,实参是从左往右给的,test3(1);给的参数被b接收了,而a收不到参数所以报错,但实际上这种函数存在就会报错
函数声明和定义分离时,缺省参数不能在函数声明和定义中同时出现,规定必须函数声明给缺省值
如下代码所示
#include<iostream>
using namespace std;
void test2(int a, int b =3);
#include"pc.h"
void test2(int a, int b = 111)
{
cout << a << " " << b << endl;
}
#include"pc.h"
int main()
{
test2(1);
test2(22, 222);
return 0;
}
由于两种缺省值互相冲突,所以不可以这样(即使值相同也不可以)
修改方法只能是在声明处给缺省值,在函数处不给缺省值,因为主函数通过头文件的函数声明才能调用函数本身
修改后代码为
#include"pc.h"
void test2(int a, int b)
{
cout << a << " " << b << endl;
}
#include<iostream>
using namespace std;
void test2(int a, int b =3);
这篇文章到这里就结束啦,喜欢的可以点一下赞
(๑′ᴗ‵๑)I Lᵒᵛᵉᵧₒᵤ❤