基本介绍
C++的起源
1979年,当时的 Bjarne Stroustrup 正在⻉尔实验室从事计算机科学和软件⼯程的研究⼯作。⾯对项⽬中复杂的软件开 发任务,特别是模拟和操作系统的开发⼯作,他感受到了现有语⾔(如C语⾔)在表达能⼒、可维护性 和可扩展性⽅⾯的不⾜。
1983年,Bjarne Stroustrup 在C语⾔的基础上 添加了 ⾯向对象编程 的特性,设计出了C++语⾔的雏形, 此时的C++已经有了类、封装、继承等核⼼概念,为后来的⾯向对象编程奠定了基础。这⼀年该语⾔被正式命名为C++。
重点:C++祖师爷——Bjarne Stroustrup
C++——在C语⾔的基础上产生的
可以进行C语言的过程化程序设计
可以进行以抽象数据类型为特点的基于对象的程序设计
可以进行面向对象的程序设计
C++的发展
时间:1998年
阶段:C++98
内容:第一个版本发布,绝大多数编译器都支持,得到了国际标准化组织(ISO)和美国标准化协会认可,以模板方式重写
C++
标准库,引入了STL
(标准模板库)。
时间:2011年
阶段:C++11
内容:增加了许多特性,使得
C++
更像一种新语言,比如:正则表达式、基于范围for循环、auto关键字、新容器、列表初始化、标准线程库等
时间:2020年
阶段:C++11
内容: 引入了许多新的特性,比如:模块(Modules)、协程(Coroutines)、范围(Ranges)、概念(Constraints)等重大特性,还有对已有特性的更新:比如Lambda支持模板、范围for支持初始化等
目前主要实用标准为 C++98
和 C++11
命名空间
#include <iostream>
using namespace std;
namespace ONE {int n = 3;
}namespace TWO {int n = 4;
}int main() {cout << ONE::n << endl;cout << TWO::n << endl;return 0;
}
命名空间的定义
namespace 关键字{//内容——可以定义变量/函数/类型等
}
#include <iostream>
using namespace std;
namespace ONE{int n = 3;namespace TWO {int n = 4;}
}int main() {cout << ONE::n << endl;cout << ONE::TWO::n << endl;return 0;
}
命名空间的使用
一共有三种方法:
方法一:指定命名空间访问(推荐)
// 指定命名空间访问
#include <iostream>
using namespace std;
namespace ONE{int n = 3;
}int main() {cout << ONE::n << endl;return 0;
}
//using将命名空间中某个成员展开
#include <iostream>
using namespace std;
namespace ONE{int n = 3;
}
using ONE::n;
int main() {cout << n << endl;return 0;
}
//展开命名空间中全部成员
#include <iostream>
using namespace std;
namespace ONE{int n = 3;
}
using namespace ONE;
int main() {cout << n << endl;return 0;
}
输入输出
#include <iostream>
using namespace std;int n = 3;int main() {cout << n << endl;//此处endl写成'/n'也是同样的效果return 0;
}
缺省函数
缺省参数是声明或定义函数时为函数的参数指定⼀个缺省值。在调⽤该函数时,如果没有指定实参 则采⽤该形参的缺省值,否则使⽤指定的实参。
缺省参数分为全缺省和半缺省参数• 全缺省就是全部形参给缺省值
• 半缺省就是部分形参给缺省值。(不是一半哦)
•C++规定半缺省参数必须从右往左依次连续缺省,不能间隔跳跃给缺省值。
• 带缺省参数的函数调⽤,C++规定必须从左到右依次给实参,不能跳跃给实参。
#include <iostream>
using namespace std;
//全缺省
void Print1(int a = 1, int b = 2) {cout<<"全缺省"<< endl;cout <<a<<endl;cout <<b<< endl;}
//半缺省
void Print2(int a , int b ,int c=3) {cout << "半缺省" << endl;cout <<a<< endl;cout <<b<< endl;cout <<c<< endl;
}int main() {//全缺省——不给参数Print1();//全缺省——给参数Print1(4, 5);//半缺省——给必要参数Print2(1,2);//半缺省——给所有参数Print2(1, 2, 4);return 0;
}
函数重载
#include <iostream>
using namespace std;void func(int a) {cout << a << endl;
}void func(int a,int b) {cout << a<<b << endl;
}void func(double a) {cout << a << endl;
}int main() {func(1);func(1, 2);func(1.1111);return 0;
}
引用
引用的概念
#include<iostream>
using namespace std;int main()
{
int a = 0;
// 引⽤:b和c是a的别名
int& b = a;
int& c = a;
// 也可以给别名b取别名,d相当于还是a的别名
int& d = b;
++d;
// 这⾥取地址我们看到是⼀样的
cout << &a << endl;cout << &b << endl;
cout << &c << endl;
cout << &d << endl;
return 0;}
引用的特性
• 引⽤在定义时必须 初始化• ⼀个变量可以有多个引⽤(土豆有很多个别名:洋芋、马铃薯)• 引⽤⼀旦引⽤⼀个实体,再不能引⽤其他实体(洋芋只能是土豆的别名,不能再成为其它蔬菜的别名)这一点注意与指针区分开!
引用的使用
#include<iostream>
using namespace std;
//引用传参
void Swap(int& rx, int& ry){int tmp = rx;rx = ry;ry = tmp;}int main(){int x = 0, y = 1;cout << x << " " << y << endl;Swap(x, y);cout << x << " " << y << endl;return 0;}
int arr[5] = { 0 };//全局变量int& func(int n) {return arr[n];
}int main() {cout << arr[4] << endl;func(4)=1;//改变了arr[4]的值为1cout << arr[4] << endl;return 0;
}
const引用
可以引⽤⼀个const对象,但是必须⽤const引⽤。const引⽤也可以引⽤普通对象原因:因为对象的访问权限在引⽤过程中 可以缩⼩ ,但是 不能放⼤ 。
注意 :类似 int& rb = a*3; double d = 12.34; int& rd = d; 这样⼀些场景下a*3的和结果保存在⼀个临时对象中, int& rd = d 也是类似,在类型转换中会产⽣临时对象存储中间值,也就是时,rb和rd引⽤的都是临时对象,⽽C++规定临时对象具有常性,所以这⾥ 就触发了权限放⼤,必须要⽤const引⽤才可以。(临时对象:编译器需要⼀个空间暂存表达式的求值结果时临时创建的⼀个未命名的对象)
指针和引用的关系
引用 | 指针 | |
开不开空间? | 不开 | 开 |
初始化? | 必须初始化 | 建议初始化,但不必须 |
改变对象? | 引⽤⼀个对象后,不能再引⽤其他对象 | 可以改变指向对象 |
访问对象? | 可以直接访问 | 需要解引⽤ |
sizeof中含义 | 引⽤类型的⼤⼩ | 地址空间所占字节个数(32位平台下 占4个字节,64位下是8byte) |
安全性 | 更安全 | 空指针和野指针的问题 |
内联函数
nline int Add(int x, int y)
{return x + y;
}
• inline对于编译器⽽⾔只是⼀个建议。也就是说,你加了inline编译器也可以选择在调⽤的地⽅不展开,不同编译器关于inline什么情况展开各不相同,因为C++标准没有规定这个。inline适⽤于频繁调用的短小函数,对于递归函数,代码相对多⼀些的函数,加上inline也会被编译器忽略。
• C++设计了inline⽬的就是替代C的宏函数C语⾔实现宏函数也会在预处理时替换展开,但是宏函数实现很复杂很容易出错的,且不⽅便调试
#define ADD(x, y) ((x) + (y)) //通过宏函数实现ADD,复杂易错
• inline不建议声明和定义分离到两个⽂件,分离会导致链接错误。因为inline被展开,就没有函数地址,链接时会出现报错。
内联函数特点:
- 在
Debug
模式下,函数不会进行替换,可以进行调试- 在
Realse
模式下,函数会像宏函数一样展开,提高程序运行速度- 内联函数弥补了宏函数的不足,同时吸收了宏函数速度快的优点
补充:
nullptr
#ifndef NULL#ifdef __cplusplus#define NULL 0#else#define NULL ((void *)0)#endif#endif
nullptr是⼀个特殊的关键字,nullptr是⼀种特殊类型的字⾯量,它可以转换 成任意其他类型的指针类型。使⽤nullptr定义空指针可以避免类型转换的问题,因为nullptr只能被 隐式地转换为指针类型,⽽不能被转换为整数类型。