个人主页
创作不易,感谢大家的关注!
文章目录
⭐前言
C++起源于1979年,当时Bjarne Stroustrup博士在面对项目复杂软件开发任务时,特别是模拟和操作系统的开发工作中,他感受到了C语言的表达等方面的不足。于是在1983年,Bjarne Stroustrup博士在C语言的基础上添加了面向对象编程的特性,为后面的面向对象编程奠定了基础,为了区分C两者语言,于是命名为C++。
因此,C++也可以进行C语言的功能。
版本更新过程:
🏠一、C++的第一个程序
由于前面我们说过,C++是在C语言的基础上编写而成的,因此在语法方面C++也兼容绝大多数C语言的语法。但需要注意的是,在定义文件过程中,需要将文件后缀名称.c更改为.cpp,编译器才会调用C++的编译器进行编译。
下面给大家演示一下代码实现过程:
//test.cpp
#include<stdio.h>
int main()
{
printf("hello world\n");
return 0;
}
有人可能会问,C++有没有自己的一套程序实现上述过程呢?答案肯定是有的。下面就是C++的实现方式:
//test.cpp
#include<iostream>
using namespace std;
int main()
{
cout << "hello world" << endl;
return 0;
}
这里可能有些代码没看懂,没关系,下面都会讲到。
🚘二、命名空间
1. namespace价值
在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。而使用命名空间的目的就是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的。
例如:
#include<stdio.h>
#include<stdlib.h>
int rand = 10;
int main()
{
//编译报错:rand重定义,以前定义是"函数"
printf("%d", rand);
return 0;
}
2. namespace定义
①定义命名空间时,需要使用namespace关键字,并在后面跟上命名空间的名字,然后接一对{},在{}中即为命名空间的成员。命名空间可以定义变量、函数、类型等。
②namespace的本质是定义一个域,这个域跟全局域各自独立,因此不同的域可以定义相同的变量名。
③C++中域有函数局部域,全局域,命名空间域,类域。而域影响的是在编译时语法查找一个变量或函数等的定义逻辑,因此就产生出域隔离。
④namespace只能定义在全局,还可以嵌套定义。
⑤项目工程中多⽂件中定义的同名namespace会认为是⼀个namespace,不会产生冲突。
⑥C++标准库都放在⼀个叫std(standard)的命名空间中。
3. 命名空间的使用
编译查找一个变量的声明或定义时,默认只会在局部或全局进行查找,而不会到命名空间里面进行查找。通常我们会有三种方式来使用命名空间中定义的变量或函数:
- 指定命名空间访问。
- 用using将命名空间中的某个成员展开。
- 展开命名空间中的全部成员。
以下代码分别演示上述所讲的方式:
// 指定命名空间访问
int main()
{
printf("%d\n", A::a);
return 0;
}
// using将命名空间中某个成员展开
using A::b;
int main()
{
printf("%d\n", A::a);
printf("%d\n", b);
return 0;
}
// 展开命名空间中全部成员
using namespce A;
int main()
{
printf("%d\n", a);
printf("%d\n", b);
return 0;
}
🎉三、C++的输入和输出
我们用一段代码来讲述有关知识:
#include<iostream>
using namespace std;
int main()
{
cout << "hello world" << endl;
return 0;
}
这里我们要知道:cout是输出时使用的,而作用相当于C语言中的printf;还有一个是cin,作用相当于C语言中的scanf。
在写C++有关代码时,我们要注意以下几点:
⚫在使用cout标准输出对象和cin标准输入对象时,必须包含 < iostream >头文件以及按命名空间使用方法使用std。
⚫endl是C++中特殊的符号,表示换行输出。
⚫ << 是流插入运算符,>> 是流提取运算符。
⚫C++的输入和输出更方便,不需向printf/scanf输入输出那样,需要手动指定格式。C++的输入和输出可以自动识别变量的类型。
⚫cout/cin/endl等都属于C++标准库,而C++标准库都放在⼀个叫std(standard)的命名空间中,所以要通过命名空间的使用方式来使用它们。
🎡四、缺省参数
缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则使用指定的实参。
注: 缺省参数不能在函数声明和定义中同时出现。缺省值必须为常量或者全局变量。
1. 全缺省
全缺省顾名思义就是全部形参给缺省值。
2. 半缺省
半缺省就是部分形参给缺省值。
注意: C++规定半缺省参数必须从右到左依次连续缺省,不能间隔跳跃给缺省值。
🎈五、函数重载
C++⽀持在同⼀作用域中出现同名函数,但是要求这些同名函数的形参不同,可以是参数个数不同或者类型不同。这样C++函数调用就表现出了多态行为,使用更灵活。而C语言是不支持同⼀作用域中出现同名函数的。
🛴六、引用
1. 引用的概念及定义
引用不是新定义⼀个变量,而是给已存在变量中取了⼀个别名,而编译器不会为引用变量开辟新的内存空间,它和它引用的变量共用同一块内存空间。
C++中为了避免引入太多的运算符,会复用C语言的⼀些符号,在这里引用的符号和取地址使用同一个符号为&。
2. 引用的特性
1.引用在定义时必须初始化
2.一个变量可以有多个引用
3.引用一旦引用一个实体,再不能引用其它实体
3. 引用的使用场景
引用主要是用于传参和引用做返回值中减少拷贝的次数提高效率和改变引用对象时同时改变被引用对象。
引用传参和指针传参的功能类似,但引用传参相对更加方便一些。
void Swap(int& a, int& b)
{
int temp = a;
a = b;
b = temp;
}
4. const引用
我们可以引用一个const对象,但是必须要使用const引用。但需要注意的是:const引用可以引用普通的对象,因为对象的访问权限在引用过程中可以缩小,但不能放大。
int main()
{
const int a = 10;
// int& ra = a会产生编译报错,因为这里的引用是对a的权限放大
const int& ra = a;
int b = 20;
// 这里的引用是对b访问的权限缩小
const int& rb = b;
return 0;
}
5. 引用和指针的关系
引用的底层其实还是指针,但它们两者也有一定的区别,不可互相替代。
1.在语法方面上,引用是一个变量的取别名,不开辟空间;而指针是存储一个变量的地址,需要开辟空间。
2.引用在定义是必须初始化,而指针是建议初始化,但不是必须。
3.引用在初始化时引用⼀个对象后,就不能再引用其他对象;而指针可以不断地改变指向对象。
4.引用可以直接访问指向的对象,而指针需要解引用才能访问所指向的对象。
5.sizeof的含义不同。引用的结果为引用类型的大小,而指针始终是地址空间所占字节个数的大小。
注:32位平台下占4个字节,64位平台下占8个字节。
6.指针很容易出现空指针或野指针的问题,而引用很少出现,因此引用使用起来相对更安全⼀些。
🚃七、内联函数
⽤inline修饰的函数叫做内联函数,在编译时,C++编译器会在调用内联函数的地方展开,这样的调用就不需要建立栈帧减少开销,从而提升了程序运行的效率。
在我们之前用C语言实现宏函数时也会在预处理时替换展开,但是宏函数实现很复杂并且容易出错,不方便调试,因此在C++中设计了inline目的就是替代C的宏函数。
inline void Fun(int& a, int& b)
{
int tmp = a;
a = b;
b = tmp;
}
int main()
{
int a = 10, b = 20;
Fun(a, b);
return 0;
}
在使用内联函数是,需要注意的是:inline不建议声明和定义分离到两个文件,分离会导致链接错误。 因为当inline被展开时,就找不到函数的地址了,链接也就找不到了。
🎄八、nullptr的介绍
在C++11中引入了一个特殊的关键字:nullptr。它是一种特殊类型的字面量,可以转换成任意其他类型的指针类型。因此在使用nullptr定义空指针时可以避免类型转换的问题。而我们之前在学习C语言中出现的NULL实际上是一个宏,在C++中可能被定义为字面常量0或无类型指针变量。