文章目录
- 1、前言
- 2、C++的关键字
- 2.1C语言32关键字
- 2.2C++关键字(63个)
- 3、命名空间
- 4、输入输出(cout、cin)
- 4、缺省参数
- 5、函数重载
- 6 引用
- 6.1 引用的定义
- 6.2 引用的特性
- 6.3引用的使用场景
- 6.4 实际例子
- 6.5、总结
- 7、内联函数
- 8、auto关键字
- 9、nullptr关键字
1、前言
C语言是结构化和模块化的语言,适合处理较小规模的程序。对于复杂的问题,规模较大的程序,需要高度的抽象和建模时,C语言则不合适。为了解决软件危机, 20世纪80年代, 计算机界提出了OOP(object oriented programming:面向对象)思想,支持面向对象的程序设计语言应运而生。
1982年,Bjarne Stroustrup博士在C语言的基础上引入并扩充了面向对象的概念,发明了一种新的程序语言。为了表达该语言与C语言的渊源关系,命名为C++。因此:C++是基于C语言而产生的,它既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行面向对象的程序设计。
下面请膜拜祖师爷!!!!!!!!!!!!
所以总得来说,C++是在C语言的基础上进行拓展的,它既支持C语言过程化设计的全部语法,又在弥补了许多C语言的不足。
2、C++的关键字
2.1C语言32关键字
首先我们需要看C语言的关键字有哪些:
一、数据类型关键字
序号 | 关键字 | 说明 |
---|---|---|
1 | char | 声明字符变量 |
2 | double | 声明双精度变量 |
3 | float | 声明浮点型变量 |
4 | int | 声明整型变量 |
5 | short | 声明短整型变量 |
6 | long | 声明长整型变量 |
7 | unsigned | 声明无符号类型变量 |
8 | signed | 声明有符号类型变量 |
9 | struct | 声明结构体变量 |
10 | union | 声明共用体或联合数据类型 |
11 | void | 声明函数无返回值或无参数,声明无类型指针 |
12 | enum | 声明枚举类型 |
二、控制语句关键字
1、循环语句类型关键字(5个)
序号 | 关键字 | 说明 |
---|---|---|
1 | for | 遍历循环 |
2 | do | 其后紧跟循环体 |
3 | while | 条件循环或死循环 |
4 | break | 跳出当前循环 |
5 | continue | 终止本次循环,开始下次循环 |
2、条件语句类型关键字(3个)
序号 | 关键字 | 说明 |
---|---|---|
6 | if | 条件语句 |
7 | else | 条件语句否定分支 |
8 | goto | 无条件跳转语句 |
3、开关语句类型关键字 (3个)
序号 | 关键字 | 说明 |
---|---|---|
9 | switch | 用于多条件判断语句 |
10 | case | 多条件判断语句分支 |
11 | default | 开关语句的其它分支 |
4、返回语句类型关键字(1个)
序号 | 关键字 | 说明 |
---|---|---|
12 | return | 函数返回语句 |
三、存储类型关键字(4个)
序号 | 关键字 | 说明 |
---|---|---|
1 | auto | 声明自动变量 |
2 | extern | 声明变量是在其他文件定义 |
3 | register | 声明寄存器变量 |
4 | static | 声明静态变量 |
重点说明:
1、auto关键字声明自动变量,由编译器自动分配及释放。这种变量在程序执行时被快速建立,程序退出后被自动撤销,在缺省的情况下,编译器默认所有变量都是auto的。
2、static为声明静态变量,主要有修饰变量和修饰函数的作用。
修饰变量时:
变量又分为局部变量与全局变量,当变量被修饰为静态全局变量时,它的作用域为定义之处开始,到文件结尾处结束,其它文件用extern声明也没办法使用它;当变量在函数体内被static修饰,则该变量只能在这个函数里使用,即使是同一个文件也不行,称为静态局部变量。静态变量总是存储在内存静态区,即使是程序执行完毕它的值也不会被销毁。
修饰函数时:
在函数前面加static可以使函数变为静态函数,静态函数的作用域仅局限于本文件,这样可以避免其它文件中定义的函数重名。
3、extern 关键字置于变量或函数前,表明变量或函数的定义在其它文件中。链接器在遇到此类变量时会在其它模块中解析/捆绑此标识符。
4、register
这个关键字请求 编译器尽可能地将变量存储在cpu的内部寄存器中,而不是通过通过内存寻址来访问变量,这有效地提高了效率。理解这个关键字需要弄那个明白cpu、寄存器与内存之间的关系,cpu是不直接和内存打交道的,cpu与内存之间的数据传输需要经过寄存器,故而将变量存储在寄存器可以提高运行效率。
PS:寄存器其实就是一块一块小的存储空间,只不过其存储数据要比内存快得多
四、其它关键字
序号 | 关键字 | 说明 |
---|---|---|
1 | const | 声明只读变量 |
2 | sizeof | 计算数据类型长度(字节数) |
3 | typedef | 给数据类型取别名 |
4 | volatile | 所修饰的对象不能被编译器优化 |
volatile是一种类型修饰符,编译器会对它修饰的变量进行特殊地址的稳定访问而不进行代码上的优化。那这里的优化具体指的是什么意思呢?
比如你想要吃苹果,这时你有两种选择,去苹果园(特殊地址)摘和去商店买,商店里的苹果来自苹果园。所谓的优化实际上是一种“偷懒”行为,当你每次吃苹果都只是去商店买而不去苹果园摘,就是一种优化行为。volatile关键字就是要你每次吃苹果时都只能去苹果园摘而不能去商店买,这就是特殊地址的稳定访问。因为商店里的苹果可能是坏的,已经改变的,而苹果园里的苹果一直都是新鲜的,完好的。
回到程序里一想,如果你需要某个变量的值稳定,而它又可能在程序执行过程中移到其它地方(商店)时发生改变,为了防止编译器“偷懒”,故你需要在这个关键字前用volatile修饰。
2.2C++关键字(63个)
asm | do | if | return | try | continue |
---|---|---|---|---|---|
auto | double | inline | short | typedef | for |
bool | dynamic_cast | int | signed | typeid | public |
break | else | long | sizeof | typename | throw |
case | enum | mutable | static | union | wchar_t |
catch | explicit | namespace | static_cast | unsigned | default |
char | export | new | struct | using | friend |
class | extern | operator | switch | virtual | register |
const | false | private | template | void | true |
const_cast | float | protected | this | volatile | while |
delete | goto | reinterpret_cast |
3、命名空间
1、问题引出:
这里的问题就在于出现了命名冲突,因为包含的头文件编译时候是展开所有的内容,而头文件include <stdlib.h>
中有rand命名的函数,所以会报错。
注意:在C语言中不同的域中可以存在相同的变量。
2、解决办法:namespace关键字,命名空间
3、使用命名空间的三种方式
1、全部展开
2、展开特定域
3、指定访问
4、命名空间中允许的内容
命名空间中可以嵌套命名空间,可以命名函数,结构体、类型等等
注:当多个文件的头文件包含在一起时,名字相同的命名空间会合并。
注:头文件的展开本质是拷贝,不参与编译
命名空间展开,影响的是编译器的搜索规则,参与编译。
4、输入输出(cout、cin)
4、缺省参数
全缺省
所谓的缺省参数也就是在形参中定义一个值,那么调用时候就可以不要传值,这里需要注意的是不能跳着来,要按顺序。如下图中的就发生了错误。
实践应用:
5、函数重载
#include<iostream>
using namespace std;
// 1、参数类型不同
int Add(int left, int right)
{
cout << "int Add(int left, int right)" << endl;
return left + right;
}
double Add(double left, double right)
{
cout << "double Add(double left, double right)" << endl;
return left + right;
}
// 2、参数个数不同
void f()
{
cout << "f()" << endl;
}
void f(int a)
{
cout << "f(int a)" << endl;
}
// 3、参数类型顺序不同
void f(int a, char b)
{
cout << "f(int a,char b)" << endl;
}
void f(char b, int a)
{
cout << "f(char b, int a)" << endl;
}
int main()
{
Add(10, 20);
Add(10.1, 20.2);
f();
f(10);
f(10, 'a');
f('a', 10);
return 0;
}
比
6 引用
6.1 引用的定义
6.2 引用的特性
6.3引用的使用场景
6.4 实际例子
struct SeqList
{
int* a;
int size;
int capacity;
};
void SLInit(SeqList& sl)
{
sl.a = (int*)malloc(sizeof(int) * 4);
// ..
sl.size = 0;
sl.capacity = 4;
}
void SLPushBack(SeqList& sl, int x)
{
//...扩容
sl.a[sl.size++] = x;
}
// 修改
void SLModity(SeqList& sl, int pos, int x)
{
assert(pos >= 0);
assert(pos < sl.size);
sl.a[pos] = x;
}
int SLGet(SeqList& sl, int pos)
{
assert(pos >= 0);
assert(pos < sl.size);
return sl.a[pos];
}
int main()
{
SeqList s;
SLInit(s);
SLPushBack(s, 1);
SLPushBack(s, 2);
SLPushBack(s, 3);
SLPushBack(s, 4);
for (int i = 0; i < s.size; i++)
{
cout << SLGet(s, i) << " ";
}
cout << endl;
for (int i = 0; i < s.size; i++)
{
int val = SLGet(s, i);
if (val % 2 == 0)
{
SLModity(s, i, val * 2);
}
}
cout << endl;
for (int i = 0; i < s.size; i++)
{
cout << SLGet(s, i) << " ";
}
cout << endl;
return 0;
}
struct SeqList
{
// 成员变量
int* a;
int size;
int capacity;
// 成员函数
void Init()
{
a = (int*)malloc(sizeof(int) * 4);
// ...
size = 0;
capacity = 4;
}
void PushBack(int x)
{
// ... 扩容
a[size++] = x;
}
// 读写返回变量
int& Get(int pos)
{
assert(pos >= 0);
assert(pos < size);
return a[pos];
}
};
int main()
{
SeqList s;
s.Init();
s.PushBack(1);
s.PushBack(2);
s.PushBack(3);
s.PushBack(4);
for (int i = 0; i < s.size; i++)
{
cout << s.Get(i)<< " ";
}
cout << endl;
for (int i = 0; i < s.size; i++)
{
if (s.Get(i) % 2 == 0)
{
s.Get(i) *= 2;
}
}
cout << endl;
for (int i = 0; i < s.size; i++)
{
cout << s.Get(i) << " ";
}
cout << endl;
return 0;
}
6.5、总结
引用和指针的不同点:
1. 引用概念上定义一个变量的别名,指针存储一个变量地址。
2. 引用在定义时必须初始化,指针没有要求
3. 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何
一个同类型实体
4. 没有NULL引用,但有NULL指针
5. 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32
位平台下占4个字节)
6. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
7. 有多级指针,但是没有多级引用
8. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理
9. 引用比指针使用起来相对更安全
7、内联函数
宏的坑有这么多,为了解决这些坑,所以引入了内联。内联函数和宏一样,都不去创建栈帧空间,是展开,所以这就实现了与宏等价的作用,而且还不容易出错
宏的优缺点?
优点:
1.增强代码的复用性。
2.提高性能。
缺点:
1.不方便调试宏。(因为预编译阶段进行了替换)
2.导致代码可读性差,可维护性差,容易误用。
3.没有类型安全的检查 。
C++有哪些技术替代宏?
1. 常量定义 换用const enum
2. 短小函数定义 换用内联函数
8、auto关键字
所谓auto就是自动类型转换
随着程序越来越复杂,程序中用到的类型也越来越复杂,经常体现在:
1. 类型难于拼写
2. 含义不明确导致容易出错
(typeid打印类型)
auto不能推导的场景
1. auto不能作为函数的参数
2. auto不能直接用来声明数组
9、nullptr关键字
使用nullptr虽然值是0,但是可以更好的进行类型转换
注意:
1. 在使用nullptr表示指针空值时,不需要包含头文件,因为nullptr是C++11作为新关键字引入的。
2. 在C++11中,sizeof(nullptr) 与 sizeof((void*)0)所占的字节数相同。
3. 为了提高代码的健壮性,在后续表示指针空值时建议最好使用nullptr。