C++之入门

本文介绍了C++语言的关键字,如C语言的32个关键字和C++新增的63个关键字,包括命名空间、输入输出、缺省参数、函数重载、引用、内联函数、auto关键字和nullptr的使用。文章还探讨了面向对象编程(OOP)和C++对C语言的扩展,以及一些关键概念的实战示例和注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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语言的关键字有哪些:
在这里插入图片描述
一、数据类型关键字

序号关键字说明
1char声明字符变量
2double声明双精度变量
3float声明浮点型变量
4int声明整型变量
5short声明短整型变量
6long声明长整型变量
7unsigned声明无符号类型变量
8signed声明有符号类型变量
9struct声明结构体变量
10union声明共用体或联合数据类型
11void声明函数无返回值或无参数,声明无类型指针
12enum声明枚举类型

二、控制语句关键字
1、循环语句类型关键字(5个)

序号关键字说明
1for遍历循环
2do其后紧跟循环体
3while条件循环或死循环
4break跳出当前循环
5continue终止本次循环,开始下次循环

2、条件语句类型关键字(3个)

序号关键字说明
6if条件语句
7else条件语句否定分支
8goto无条件跳转语句

3、开关语句类型关键字 (3个)

序号关键字说明
9switch用于多条件判断语句
10case多条件判断语句分支
11default开关语句的其它分支

4、返回语句类型关键字(1个)

序号关键字说明
12return函数返回语句

三、存储类型关键字(4个)

序号关键字说明
1auto声明自动变量
2extern声明变量是在其他文件定义
3register声明寄存器变量
4static声明静态变量

重点说明:
1、auto关键字声明自动变量,由编译器自动分配及释放。这种变量在程序执行时被快速建立,程序退出后被自动撤销,在缺省的情况下,编译器默认所有变量都是auto的。

2、static为声明静态变量,主要有修饰变量和修饰函数的作用。
修饰变量时:
变量又分为局部变量与全局变量,当变量被修饰为静态全局变量时,它的作用域为定义之处开始,到文件结尾处结束,其它文件用extern声明也没办法使用它;当变量在函数体内被static修饰,则该变量只能在这个函数里使用,即使是同一个文件也不行,称为静态局部变量。静态变量总是存储在内存静态区,即使是程序执行完毕它的值也不会被销毁。
修饰函数时:
在函数前面加static可以使函数变为静态函数,静态函数的作用域仅局限于本文件,这样可以避免其它文件中定义的函数重名。
3、extern 关键字置于变量或函数前,表明变量或函数的定义在其它文件中。链接器在遇到此类变量时会在其它模块中解析/捆绑此标识符。
4、register
这个关键字请求 编译器尽可能地将变量存储在cpu的内部寄存器中,而不是通过通过内存寻址来访问变量,这有效地提高了效率。理解这个关键字需要弄那个明白cpu、寄存器与内存之间的关系,cpu是不直接和内存打交道的,cpu与内存之间的数据传输需要经过寄存器,故而将变量存储在寄存器可以提高运行效率。
PS:寄存器其实就是一块一块小的存储空间,只不过其存储数据要比内存快得多
四、其它关键字

序号关键字说明
1const声明只读变量
2sizeof计算数据类型长度(字节数)
3typedef给数据类型取别名
4volatile所修饰的对象不能被编译器优化

volatile是一种类型修饰符,编译器会对它修饰的变量进行特殊地址的稳定访问而不进行代码上的优化。那这里的优化具体指的是什么意思呢?

比如你想要吃苹果,这时你有两种选择,去苹果园(特殊地址)摘和去商店买,商店里的苹果来自苹果园。所谓的优化实际上是一种“偷懒”行为,当你每次吃苹果都只是去商店买而不去苹果园摘,就是一种优化行为。volatile关键字就是要你每次吃苹果时都只能去苹果园摘而不能去商店买,这就是特殊地址的稳定访问。因为商店里的苹果可能是坏的,已经改变的,而苹果园里的苹果一直都是新鲜的,完好的。

回到程序里一想,如果你需要某个变量的值稳定,而它又可能在程序执行过程中移到其它地方(商店)时发生改变,为了防止编译器“偷懒”,故你需要在这个关键字前用volatile修饰。

2.2C++关键字(63个)

asmdoifreturntrycontinue
autodoubleinlineshorttypedeffor
booldynamic_castintsignedtypeidpublic
breakelselongsizeoftypenamethrow
caseenummutablestaticunionwchar_t
catchexplicitnamespacestatic_castunsigneddefault
charexportnewstructusingfriend
classexternoperatorswitchvirtualregister
constfalseprivatetemplatevoidtrue
const_castfloatprotectedthisvolatilewhile
deletegotoreinterpret_cast

3、命名空间

1、问题引出:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这里的问题就在于出现了命名冲突,因为包含的头文件编译时候是展开所有的内容,而头文件include <stdlib.h> 中有rand命名的函数,所以会报错。
注意:在C语言中不同的域中可以存在相同的变量。
2、解决办法:namespace关键字,命名空间
在这里插入图片描述
在这里插入图片描述
3、使用命名空间的三种方式
1、全部展开
在这里插入图片描述
2、展开特定域
3、指定访问
在这里插入图片描述
4、命名空间中允许的内容
命名空间中可以嵌套命名空间,可以命名函数,结构体、类型等等
注:当多个文件的头文件包含在一起时,名字相同的命名空间会合并。
在这里插入图片描述
注:头文件的展开本质是拷贝,不参与编译
命名空间展开,影响的是编译器的搜索规则,参与编译。

4、输入输出(cout、cin)

在这里插入图片描述

5、缺省参数

全缺省
在这里插入图片描述
所谓的缺省参数也就是在形参中定义一个值,那么调用时候就可以不要传值,这里需要注意的是不能跳着来,要按顺序。如下图中的就发生了错误。
在这里插入图片描述
半缺省
在这里插入图片描述
实践应用:

6、函数重载

在这里插入图片描述

#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;
}

在这里插入图片描述
在这里插入图片描述

7 引用

7.1 引用的定义

在这里插入图片描述

7.2 引用的特性

在这里插入图片描述
在这里插入图片描述

7.3引用的使用场景

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7.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;
}

在这里插入图片描述
在这里插入图片描述

7.5、总结

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

引用和指针的不同点:

  1. 引用概念上定义一个变量的别名,指针存储一个变量地址。
  2. 引用在定义时必须初始化,指针没有要求
  3. 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何
    一个同类型实体
  4. 没有NULL引用,但有NULL指针
  5. 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节)
  6. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
  7. 有多级指针,但是没有多级引用
  8. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理
  9. 引用比指针使用起来相对更安全

8、内联函数

在这里插入图片描述
宏的坑有这么多,为了解决这些坑,所以引入了内联。内联函数和宏一样,都不去创建栈帧空间,是展开,所以这就实现了与宏等价的作用,而且还不容易出错
在这里插入图片描述
在这里插入图片描述

宏的优缺点?
优点:
1.增强代码的复用性。
2.提高性能。
缺点:
1.不方便调试宏。(因为预编译阶段进行了替换)
2.导致代码可读性差,可维护性差,容易误用。
3.没有类型安全的检查 。
C++有哪些技术替代宏?
1> 常量定义 换用const enum
2> 短小函数定义 换用内联函数

9、auto关键字

所谓auto就是自动类型转换
随着程序越来越复杂,程序中用到的类型也越来越复杂,经常体现在:
类型难于拼写
含义不明确导致容易出错

(typeid打印类型)
在这里插入图片描述

 auto不能推导的场景
1. auto不能作为函数的参数
2. auto不能直接用来声明数组

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

10、nullptr关键字

在这里插入图片描述
使用nullptr虽然值是0,但是可以更好的进行类型转换
在这里插入图片描述

注意:
1. 在使用nullptr表示指针空值时,不需要包含头文件,因为nullptr是C++11作为新关键字引入的。
2. 在C++11中,sizeof(nullptr) 与 sizeof((void*)0)所占的字节数相同。
3. 为了提高代码的健壮性,在后续表示指针空值时建议最好使用nullptr。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值