C++入门

目录

命名空间

命名空间的定义

命名空间的使用方法

指定访问

展开访问

访问优先级

C++的输入和输出

缺省参数

函数重载

引用

要求

常引用

传值和传引用

引用和指针的区别

auto关键字

auto不能使用的场景

范围for

内联函数

补充nullptr


C++是兼容于C语言的,可以说是C语言的升级版。该篇文章将会详细介绍C++在C语言基础上的优化,新增的特性及功能。

命名空间

C++中引入了STL库,导致添加了很多关键字,变量,函数及类,这也就导致在定义一个变量的时候可能会与库中所定义的重复,这也就导致了访问冲突。所以使用命名空间使标识符的名称进行本地化,来避免命名冲突或名字污染。

命名空间的定义

定义命名空间需要使用namespace这一关键字,后面跟上名称,接{}。{}内添加需要定义的名称,类型等。如下图。

cpp 复制代码
namespace show
{
	int list;
	int name;
	double ptr;
}

命名空间不仅仅可以定义变量,还能够定义函数,结构体等类型;命名空间也满足嵌套定义,即命名空间内还有命名空间;多个同名的命名空间会合并。


命名空间的使用方法

指定访问

通过命名空间::变量名称可以指定访问命名空间内的指定指定变量。

cpp 复制代码
namespace test
{
	int cnt = 0;
	int num = 20;
}

int main()
{
	int tmp = test::num;  //指定访问test命名空间中的num
	return 0;
}

展开访问

展开的访问包括两种方式,展开命名空间中的指定变量或将整个命名空间展开。

使用using 命名空间名称::变量名称,只将单个变量引入。

cpp 复制代码
namespace test
{
	int cnt = 0;
	int num = 20;
}

int main()
{
	using test::num;   //能直接访问num,但是不能直接访问cnt
	int tmp = num;  
	return 0;
}

使用using namespace 命名空间名称,将整个命名空间引入。

cpp 复制代码
namespace test
{
	int cnt = 0;
	int num = 20;
}

int main()
{
	using namespace test;   //既能访问num也能访问cnt
	int tmp =num;
	tmp = cnt;
	return 0;
}

不论是展开单个变量还是整个命名空间,都要注意展开的变量是否和当前域中的变量或函数名称冲突。

访问优先级

++当一个变量在全局域,局部域,命名空间域中同时存在,访问的时候会先访问哪一个??++

在未展开命名空间的情况下,局部域>全局域;展开命名空间后,命名空间内的变量相当于全局域,当命名空间展开而全局域中又有相同的变量名称时,就会导致冲突。

cpp 复制代码
int num = 10;
namespace test
{
	int cnt = 0;
	int num = 20;
}
int main()
{
	int num = 30;
	int tmp =num;  //tmp取局部域的num 30
	return 0;
}
cpp 复制代码
int num = 10;
namespace test
{
	int cnt = 0;
	int num = 20;
}
int main()
{
	using namespace test;     
	int tmp =num;    //命名空间展开了,全局域也有num,此时就冲突了
	return 0; 
}

C++的输入和输出

C++的输入和输出是依靠cin和cout的。

++1)cin和cout要包含头文件<iostream>,cin和cout是在std的命名空间中定义的,所以在使用的时候要指定命名空间或直接将std展开。++

2)<<和>>分别是流插入运算符和流提取运算符,代表数据流向的方向。

++3)cin和cout与C语言的printf,scanf主要区别在于他们具有自动识别变量类型的功能,不需要再去手动输入类型了。++


缺省参数

缺省参数指的是在定义函数的时候,在形参的位置添加一个缺省值,实际上就是赋一个值。当有缺省参数后,在调用函数的时候如果不传参就会调用默认的缺省参数。传参就不会再调用缺省参数了。

cpp 复制代码
void Print(int a = 10,int b = 20)
{
	std::cout << a << b;
}

int main()
{
	Print();        //调用缺省参数
	Print(20);      //b调用缺省参数
	Print(20, 30);  //a,b均不调用缺省参数
	return 0;
}

缺省参数分为两种:全缺省,半缺省。全缺省就是所有形参都有缺省参数,半缺省就是只有部分有。

关于缺省参数,实参赋值给形参的时候是从左往右,所以在给函数缺省参数的时候不能出现左边没有给缺省值,但是右边给你缺省值的情况。

当函数的生命和定义分开的时候,缺省参数要放到声明的位置。


函数重载

C++允许在同一个作用域上,定义多个同名函数。但是为了区分这些函数,其形参列表(形参类型形参个数,形参顺序)必须不同。

cpp 复制代码
void test()
{
	std::cout << "hello C++" << std::endl;
}

void test(int a)
{
	std::cout << "hello C++" << a << std::endl;
}

以上两个函数的命名相同,形参不同构成重载。

cpp 复制代码
void test()
{
	std::cout << "hello C++" << std::endl;
}

void test(int a = 10)
{
	std::cout << "hello C++" << a << std::endl;
}

++思考:上面这两个函数是否构成重载??调用的时候会出现什么问题??++

上面的代码的参数不同构成重载,当调用test(100),即给函数传参的时候会调用第二个函数,程序能够正常运行;当调用tese(),即不传参的时候,调用哪一个是不确定的,会报错。


引用

C++中为了解决C语言复杂,麻烦的指针概念,创建了引用这一概念。引用实际上是对一个变量,对象进行取别名。比如:厕所,卫生间,茅房等,他们实际上指的是一个东西,只是名称不同。

使用方法:类型& 别名=引用实体。

cpp 复制代码
int main()
{
	int a;
	int& b = a; //b就是a的别名
	return 0;
}

上面的代码中,b就是a的别名,当b改变的时候,a同时也会改变。

要求

1)引用必须是同类型之间的;

2)引用的时候必须初始化,不能int& b;

3)一个变量可以有多个引用;

4)一旦引用了实体,就不能再引用其他实体了。

常引用

当一个变量被const修饰后,需要在引用时也加上const;

cpp 复制代码
int main()
{
	const int a = 11;
	const int& b = a;
	return 0;
}

const修饰导致a不能改变,引用后也需要满足a不能改变,即a的别名b也不能改变。

传值和传引用

引用可以用于交换函数的实现,通过引用就不再需要传指针了。

cpp 复制代码
void Swap(int& a, int& b)
{
	int tmp = a;
	a = b;
	b = tmp;
}

传值和传引用在效率上是有很大的差别的,传值需要对实参进行拷贝,而传引用就不需要,所以传引用可以大大提高效率。

引用和指针的区别

1)引用是一个变量的别名,而指针是存储变量的地址;

2)引用在定义的时候就要初始化,指针不用;

3)引用在初始化后,就不能在引用其他实体,指针可以指向其他地址;

4)指针有空指针,引用没有类似概念;

5)指针的大小是确定的,引用要看引用的类型;

6)两者访问实体的方式不同,引用更安全。


auto关键字

随着程序越来也复杂,类型越来越多,在后面使用迭代器的时候,类型名称可能会很长,为了解决这一难题。C++引入了auto关键字,它可以自动识别类型。

cpp 复制代码
int main()
{
	auto a = 10;   //自动识别为int
	auto ch = 'a'; //char 
	auto b = 1.1;  //double
	return 0;
}

auto不能使用的场景

1)用auto定义的时候,同一行不能定义多个变量;

2)不能将auto作为函数形参的类型;

3)不能用auto声明数组。


范围for

范围for是C++的一个"语法糖",可以用范围for直接实现对数组或类的遍历,不再需要像C语言一样给出范围。

cpp 复制代码
int main()
{
	int arr[] = { 1,5,6,5,5,4,648,41,6 };
	for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
		std::cout << arr[i] << " ";

	for(auto e:arr)
		std::cout << e << " ";

	return 0;
}

上面两段循环代码结果是相同的,可以看出范围for就是将数组的值赋给了e,不需要给条件当到达数组结尾时自动停止。

依次取数组中的数据赋给e,自动迭代,自动判断结束,使用于各类数组。


内联函数

C语言中宏函数写起来复杂,可读性差,但是其效率高,有存在的必要。所以C++中引用了内联函数来取代宏函数。使用方法简单,就是在自定义函数前面加上inline关键字。

cpp 复制代码
inline int sum(int x,int y)
{
	return x + y;
}

内敛函数与宏函数的效果一样,在预处理阶段,将内联函数更换到源代码的位置,所以内联函数会是形成的可执行程序变大。

内联函数大多适用于代码少,需要频繁调用的函数上。

实际上,一个函数能否成为内联函数还是取决于编译器,虽然在函数前加上inline,但是这只是对编译器建议一下,能否成为内联函数取决于编译器。通常代码长,是有递归的函数,编译器一般都不会让其成为内联函数。

编译器在处理内联函数的时候,不会给其安排地址,所以在定义内敛函数的时候不能将声明和定义分离。

补充nullptr

在C语言中,NULL实际上是一个宏定义:#define NULL 0;NULL实际上不是指针,是0;只是我们在定义一个指针为NULL是,将NULL强制类型转化为了地址。

C++中引入的nullptr效果于NULL类似,但是nullptr不是0,而是0的地址:#define nullptr (void*)0;

相关推荐
Vitalia1 小时前
从入门到精通Rust:资源库整理
开发语言·后端·rust
放羊郎1 小时前
CUDA兼容NVIDA版本关系
开发语言·后端·rust
奔跑吧邓邓子2 小时前
【Python爬虫(69)】解锁游戏数据宝藏:Python爬虫实战攻略
开发语言·爬虫·python·游戏
arong_xu2 小时前
C++核心指导原则: 错误处理
开发语言·c++
nqqcat~2 小时前
MFC学习笔记-1
c++·mfc
疯狂小伟哥2 小时前
【无标题】PHP-get_definde_vars
开发语言·php
久绊A3 小时前
Ubuntu及其衍生系统安装Python
开发语言·python
ThereIsNoCode3 小时前
「软件设计模式」责任链模式(Chain of Responsibility)
开发语言·责任链模式
m0_726365833 小时前
某宝同款百度盘不限速后台系统源码_卡密系统_Java账号管理系统部署方案
java·开发语言
zr想努力3 小时前
Lua语言入门(自用)
开发语言·lua