【C++】C++入门

在这里插入图片描述
个人主页~


一、什么是C++

C语言是结构化和模块化的语言,适合处理小规模的程序,对于复杂的问题、规模较大的程序,需要高度的抽象和建模时,C语言则不合适,这时出现了面向对象的思想,支持面向对象的程序设计语言应运而生

C++基于C语言产生,是在C语言的基础上实现的,也就是说:C++兼容C语言的语法

java、c++都是面向对象的语言

二、C++关键字

在这里插入图片描述
我在网站上找到了C++的关键字,C++一共有63个关键字,其中包含着C语言的32个关键字(红色标识)

三、命名空间

我们知道在C语言中,变量的名字是不能够相同的,否则不会编译通过,但是在全局定义变量时,我们可能会定义一个与包含头文件中某个变量名字相同的已经被定义过的变量、类型或函数
在这里插入图片描述

使用命名空间可以避免这种情况的发生,使程序更加明了

1、命名空间的定义

这里我们需要提到上方图中的关键字:namespace

namespace name
{
    //......
}

namespace后面跟着命名空间的名字,可以任取,花括号中是命名空间的成员,可以有变量、函数、自定义类型以及嵌套命名空间

namespace slm
{
	int rand = 1;

	int Add(int x, int y)
	{
		return x + y;
	}

	typedef struct sNode
	{
		int a;
		struct sNode* next;
	}sNode;

    namespace super
    {
    	int rand = 2;
    }
}

同一个工程中,允许存在多个相同的命名空间,编译器最后会合成到同一个命名空间中,也就是被相同命名的空间都在一个位置,就像是对于我们国家来说,其中的成员不管是山东省还是台湾省,都属于中国

2、命名空间的使用

(1)加命名空间名称及作用域限定符

int main()
{
	printf("%d\n", slm::rand);
	return 0;
}

在这里插入图片描述

(2)使用using将命名空间中某个成员引入

using slm::Add;
int main()
{
	printf("%d\n", slm::rand);
	printf("%d\n", Add(1, 2));
	return 0;
}

在这里插入图片描述

(3)使用using namespace命名空间名称引入

#include <iostream>

namespace slm
{
	int r = 1;

	int Add(int x, int y)
	{
		return x + y;
	}

	typedef struct sNode
	{
		int a;
		struct sNode* next;
	}sNode;

	namespace super
	{
		int r = 2;
	}
}
using namespace slm;
int main()
{
	printf("%d\n", r);
	printf("%d\n", Add(1, 2));
	return 0;
}

在这里插入图片描述

四、输入输出

#include <iostream>
//std是标准库的命名空间名,C++中标准库的定义都放在这个命名空间中
using namespace std;
int main()
{
	cout << "HELLO WORLD" << endl;
	return 0;
}

在这里插入图片描述
1、cout是标准输出对象,cin是标准输入对象

2、头文件iostream(为了与C语言头文件进行区分,以及更好地使用命名空间,C++头文件不带.h)

3、cout和cin是全局的流对象,endl相当于’\n’,是特殊的C++符号,表示换行输出

4、<<是流插入运算符,>>是流提取运算符

5、C++的输入输出可以自动识别变量类型

#include <iostream>
using namespace std;
int main()
{
    int a;
    double b;
    char c;
//三个类型不同的变量
    cin >> a;
    cin >> b >> c;
//流提取,也就是相当于C语言中的scanf
    cout << a << endl;
    cout << b << " " << c << endl;
//流插入,对于第二行来说,先插入b值,再插入空格,再插入c值,相当于C语言中的printf
    return 0;
}

在这里插入图片描述
这里对于C++标准库的命名空间,使用using namespace std 可以全部展开,不全部展开也有别的使用方法:也就是std::

int main()
{
    int a;
    double b;
    char c;

    std::cin >> a;
    std::cin >> b >> c;

    std::cout << a << std::endl;
    std::cout << b << " " << c << std::endl;
    return 0;
}

在这里插入图片描述
或者

using std::cin;
using std::cout;
using std::endl;

int main()
{
    int a;
    double b;
    char c;

    cin >> a;
    cin >> b >> c;

    cout << a << endl;
    cout << b << " " << c << endl;
    return 0;
}

在这里插入图片描述

五、缺省参数

1、缺省参数的概念

缺省参数就是声明或定义函数时,为函数的参数指定一个缺省值,在调用函数时,如果没有实参则采用该形参的缺省值,如果有实参则采用实参

C语言不支持缺省参数

缺省值必须是常量或者全局变量

using namespace std;

void func(int i = 0)
{
	cout << i << endl;
}

int main()
{
	func();
	func(1);
	return 0;
}

在这里插入图片描述

2、缺省参数的分类

缺省参数不能在函数声明和定义中同时出现,通常我们把缺省参数放到头文件中,在源文件中就不能再次指定缺省参数

(1)全缺省参数

using namespace std;

void func(int i = 0, int j = 1, int k = 2)
{
	cout << i << " ";
	cout << j << " ";
	cout << k << " ";
	cout << endl;
}

int main()
{
	func();
	func(1);
	func(1, 2);
	func(1, 2, 3);
	return 0;
}

在这里插入图片描述

(2)半缺省参数

半缺省的缺省值不是随便给的,只能是从右往左给,也就是说,一个非缺省参数的左边的参数不可能是缺省参数

using namespace std;

void func(int i, int j = 1, int k = 2)
{
	cout << i << " ";
	cout << j << " ";
	cout << k << " ";
	cout << endl;
}

int main()
{
	//func();
	func(1);
	func(1, 2);
	func(1, 2, 3);
	return 0;
}

在这里插入图片描述

六、函数重载

1、函数重载的概念

C++允许在同一个作用域中声明几个功能类似的同名函数,这些同名函数的参数个数、类型、类型顺序可以不同,用来处理实现功能类似但数据类型不同的问题

using namespace std;
//参数类型不同
int Add(int x, int y)
{
	return x + y;
}

double Add(double x, double y)
{
	return x + y;
}
//参数个数不同
void func()
{
	cout << "func()" << endl;
}

void func(int a)
{
	cout << "func(int a)" << endl;
}
//参数类型顺序不同
void func(int x, char y)
{
	cout << "func(int x, char y)" << endl;
}

void func(char y, int a)
{
	cout << "func(char y, int a)" << endl;
}

int main()
{
	cout << Add(10, 20) << endl;
	cout << Add(11.1, 22.2) << endl;

	func();
	func(1);

	func(1, 'a');
	func('a', 1);
	return 0;
}

在这里插入图片描述
这里我们懂了chognzai函数重载的概念,其实cout可以自动识别数据类型也是一种重载

2、C++支持函数重载的原理

C++支持函数重载的原理是名字修饰

在C/C++中,一个程序需要经过预处理、编译、汇编、链接才能运行,每个项目由多个源文件构成,如果文件A中没有某函数的定义,但使用了,这样编译器会找不到函数的地址,另一文件B中有,在链接时,可以找到B中的函数地址,然后链接到一起,在链接时函数名会被修饰

因为Windows下的vs修饰规则比较复杂,我们选择在Linux下观察
结论:gcc的函数修饰后名字不变,而g++的函数修饰变成 _Z+函数长度+函数名+类型首字母

也就是说,C语言没法支持重载,同名函数没办法区分,C++可以通过名字修饰的方式形成不同名字的函数,只要参数不同,修饰出来的名字就不一样,就支持了重载

两个函数的函数名和参数相同不支持重载,调用时编译器没法区分

七、引用

1、引用的概念

引用就是给已有的变量取别名,它和它引用的变量共用同一块内存空间

using namespace std;

int main()
{
	int a = 10;
	int& b = a;
	//数据类型+& 变量名 = 已定义的变量名;
	cout << a << endl;
	cout << b << endl;
    printf("%p\n", a);
	printf("%p\n", b);
	return 0;
}

在这里插入图片描述

2、引用的特性

(1)在定义时必须初始化

(2)一个变量可以有多次引用

(3)一旦引用一个实体,就不能再引用其他实体

总的来说:引用要初始化,变量可以看成母本,引用可以看成子本,母本可以有多个子本,但子本只能有一个母本

3、常引用

using namespace std;

int main()
{
	int a = 10;//当a为变量时
	//int& ra = a;	(√)平移引用
	//const int& ra = a; (√)缩小引用
//我们可以用const和非const来修饰int&

	const int a = 10;//当a为常量时
	//int& ra = a;(×)方法引用
	//const int& ra = a;(√)平移引用
//我们只能用const来修饰
	return 0;
}

把变量修饰成常量取消了他变化的能力,缩小了能力,在引用时,可以缩小引用,可以平移引用,但是不能放大引用

4、引用的使用

引用跟指针很像,C++老大在优化指针时搞出来的

(1)做参数

void Swap(int& a, int& b)
{
	int tmp = a;
	a = b;
	b = tmp;
}

(2)做返回值

引用返回使用时要注意一个问题:如果函数返回时,出了函数作用域返回对象还在,则可以使用引用返回,如果已经回收系统,则必须使用传值返回

在函数栈帧的那篇博客中详细描述过,在函数调用结束后,函数的地址就没办法再访问到,如果没有函数再开辟栈帧,那么里面的内容还能够访问到,如果有,那么就会被覆盖
有关于函数栈帧的详细解说可以看这里~

所以引用返回所引用的值最好是全局变量或者高于函数局部变量的局部变量

5、传值和传引用的效率

在传递小的、简单的数据类型时,传值效率高
在传递大的、复杂的数据类型时,传引用或指针的效率更高

6、引用和指针的区别

我在前面提到过引用和指针很像,其实它们的底层实现是一模一样的

int main()
{
	int a = 0;
	int* pa = &a;
	int& ra = a;
	return 0;
}

在这里插入图片描述
我们可以看到这里的反汇编代码是一模一样的
不同点:

类型引用指针
概念定义一个变量的别名存储一个变量的地址
定义必须初始化没有要求
指向性只能引用一个实体可以指向任何同一类型的实体
NULL没有NULL引用有NULL指针
在sizeof中的意义引用类型的大小地址空间所占字节个数
自加引用自加就是被引用的实体加一指针自加就是向后偏移一个类型的大小
多级没有多级引用有多级指针
访问实体方式编译器自己处理显示解引用
安全性较安全较危险

八、内联函数

1、内联函数的概念

以关键字inline修饰的函数叫内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数调用建立栈帧的开销,提升程序运行的效率

2、内联函数的特性

(1)inline是一种空间换时间的做法,如果函数被当做是内联函数处理,在编译阶段会用函数体替换函数调用,它可能会使目标文件变大,但它减少了调用的开销,提高了程序的运行效率

(2)inline对于编译器来说并不是命令而是一种建议,一般来说,函数规模较小、不是递归且频繁调用的函数用inline修饰,否则会被编译器忽略

(3)inline不能够声明与定义分离,会导致链接错误,因为编译器需要看到内联函数的定义才能内联展开

C++中的内联函数对标C中的宏,宏的优点增强代码的复用性以及提高性能缺点不方便调试、代码可读性可维护性差、没有类型安全的检查,所以对于常量定义来说,换用const和enum,对于短小函数的定义来说,C++提供的办法就是换用内联函数

//func.h
#include <iostream>
using namespace std;
inline void func(int i);//声明

//func.c
#include "func.h"
void func(int i)
{
	cout << i << endl;
}//定义

//test.c
#include "func.h"
int main()
{
	func(1);
	return 0;
}

在这里插入图片描述
结果显示链接错误,所以inline声明与定义要在一个头文件中

九、auto关键字

1、auto关键字简介

当程序越来越复杂,程序中所用的类型也会越来越复杂,以前我们会用typedef来取别名,但是typedef的局限性在于不能识别类型,所以auto关键字就出现了
老标准:使用auto修饰的变量,是具有自动存储器的局部变量,但局部变量默认就是自动存储器,所以没人使用
C++11的新标准:在编译时期自动类型推导

这里我们介绍一个运算符typeid,用于在运行时获取类型信息

using namespace std;
int TestAuto()
{
	return 1;
}
int main()
{
	int a = 10;
	auto b = a;
	auto c = 'a';
	auto d = TestAuto();
//auto自动对齐右边的类型
	cout << typeid(b).name() << endl;
	cout << typeid(c).name() << endl;
	cout << typeid(d).name() << endl;
//检测bcd的类型
	return 0;
}

在这里插入图片描述
使用auto定义变量时必须对其进行初始化,在编译阶段根据初始化表达式来推到auto的实际类型,然后将其替换

2、auto的使用

(1)auto与指针和引用结合起来使用

用auto声明指针类型时,用auto和auto*没有任何区别,但auto声明引用类型时必须加&

using namespace std;
int main()
{
    int x = 10;
    auto a = &x;
    auto* b = &x;
    auto& c = x;

    cout << typeid(a).name() << endl;
    cout << typeid(b).name() << endl;
    cout << typeid(c).name() << endl;

    return 0;
}

在这里插入图片描述

(2)同一行定义多个变量

这些变量必须是相同的类型,编译器只会对第一个类型进行推导,然后用推导出来的类型定义其他的类型

(3)auto不能推导的场景

auto不能作为函数的参数
auto不能直接用来声明数组

十、基于范围的for循环

1、范围for的基本概念

我们以前使用for循环需要这么用:

using namespace std;
void TestFor()
{
    int array[] = { 1, 2, 3, 4, 5 };

    for (int* p = array; p < array + sizeof(array) / sizeof(array[0]); ++p)
        cout << *p << " ";

    cout << endl;

    for (int i = 0; i < sizeof(array) / sizeof(array[0]); ++i)
        array[i] *= 2;

    for (int* p = array; p < array + sizeof(array) / sizeof(array[0]); ++p)
        cout << *p << " ";
}

在这里插入图片描述
对于范围for来说,for循环后的括号由冒号分成两部分,第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围

并且它跟普通for循环类似的是,可以用continue结束此次循环和break退出循环

void TestFor()
{
    int array[] = { 1, 2, 3, 4, 5 };
    for (auto e : array)
        cout << e << " ";

    cout << endl;
    
    //这里e只是一份复制品,需要引用才能修改array当中的值
    for (auto& e : array)
        e *= 2;

    for (auto e : array)
        cout << e << " ";
}

在这里插入图片描述

2、范围for使用条件

(1)范围for循环迭代的范围必须确定,对于数组来说,就是第一个元素到最后一个元素
(2)迭代的对象要实现++和==的操作

十一、指针空值nullptr

指针空值我们以前使用NULL,但在C++中,NULL是被赋予值的,为0,在C中,NULL就是(void*)0,所以我们产生了新的指针空值nullptr,在C++中代表着(void*)0

在使用nullptr时不需要引入其他头文件

在C++11中,sizeof(nullptr) == sizeof((void * )0)

在C++中表示指针空值时最好使用nullptr


今日分享结束~
在这里插入图片描述

  • 180
    点赞
  • 126
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 115
    评论
C入门PDF是一种提供初学者学习C语言基础知识的电子文档。C语言被广泛应用于软件开发领域,是一种高级计算机编程语言学习C语言是许多计算机科学专业学生和编程爱好者的首选。 C入门PDF通常包含基本的C语言语法和常用的编程概念。它们可能包括变量、数据类型、运算符、条件语句、循环语句和函数等基础知识的介绍。此外,它们还可能包含一些简单的编程示例和练习,帮助初学者理解并应用所学知识。 通过学习C入门PDF,初学者可以逐步建立对C语言的理解和掌握。他们可以学习如何编写简单的C程序,并逐渐提高他们的编程能力。C语言是一种结构化的编程语言,因此通过学习C语言,初学者也可以培养良好的编程习惯和逻辑思维能力。 对于初学者来说,C入门PDF是一个方便而有效的学习工具。他们可以根据自己的进度和需要,在任何时间和地点学习C语言。通过自主学习,初学者可以在自己的学习节奏和理解能力下进行学习,不受时间和空间的限制。 C入门PDF是许多在线教育平台、编程社区和计算机科学教育机构提供的免费资源。因此,初学者可以轻松获取这些资源,并根据自己的学习需求选择最适合自己的C入门PDF。 总之,C入门PDF是一种方便且有效的学习资源,可以帮助初学者掌握C语言的基础知识和编程技能。通过学习C语言,初学者可以为自己的编程之路打下坚实的基础。
评论 115
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

s_little_monster_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值