IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【C++】C++入门 -> 正文阅读

[C++知识库]【C++】C++入门


💬推荐一款模拟面试、刷题神器 、从基础到大厂面试题:👉点击跳转刷题网站进行注册学习?


目录

一、命名空间

1、作用域限定符::

二、命名空间namespace

1、命名空间的嵌套

2、相同命名空间会被合并

3、命名空间的全部展开与部分展开

三、C++中的输入输出

四、缺省参数

1、全缺省参数

2、半缺省参数

五、函数重载

1、参数类型不同

2、参数个数不同

3、类型顺序不同

4、函数重载的原理

5、为什么不能根据函数的返回值进行函数重载

六、引用

1、引用特性

1.1引用在定义的时候必须初始化

1.2一个变量可以有多个引用

1.3一旦成为了某个变量的引用,引用将一直效忠这个变量

2、常引用(指针和引用的赋值,权限可以缩小不能扩大)

2.1对常量的引用

2.2对const常量的引用

2.3隐式、强制类型转换的引用

2.4传参时的权限问题

3、引用的使用场景

3.1引用做参数

引用做参数的优势

3.2引用做返回值

引用返回相较于传值返回的优势

3.3引用和指针的区别

七、inline关键字

1、inline的概念

2、inline修饰的函数的特点

3、宏的优缺点和替代

八、auto的用法

九、范围for

十、关键字nullptr


一、命名空间

C语言是没办法解决命名冲突问题的。变量、函数和类名在一个工程中往往被大量定义,那么在协作开发中,为了防止不同的小组间命名的冲突,c++引入了namespace关键字,使标识符的名称进行本地化, 以避免命名冲突或名字污染。

1、作用域限定符::

当a的前面加上域作用限定符::,a只能访问全局域,如果全局中a不存在,不会再去局部域中找,会直接报错

二、命名空间namespace

1、命名空间的嵌套

namespace jly
{
	int scanf=0;
	int Add(int a, int b)
	{
		return a + b;
	}
	namespace bjb//命名空间嵌套命名空间
	{
		struct std
		{
			int age;
			char name[10];
		};
	}
}
int main()
{
	struct jly::bjb::std student={10,"jk"};//嵌套结构体的调用
	return 0;
}

命名空间是可以嵌套命名空间的。调用时,需要一步一步指定命名空间域。如果命名空间中找不到对应变量名,将会报错。

2、相同命名空间会被合并

在同一个工程中,允许存在多个名字相同的命名空间,编译器最终会将同名命名空间里的内容进行合并。

3、命名空间的全部展开与部分展开

using namespace std;//全部展开
using std::cout;//部分展开

std是C++官方库定义的命名空间(像cout啥的就在std里面,但是c语言如printf就不在std中)

全部展开用起来方便,但命名空间就失去了命名隔离的作用了。写工程不采用,日常写小代码可以展开。

三、C++中的输入输出

int main()
{
	std::cout << "hello world" << std::endl;//<<流插入运算符
	int a = 0;
	std::cin >> a;//>>流提取运算符
}

1. cout和cin是全局的流对象,endl是特殊的C++符号,表示换行输出,使用cout标准输出对象(控制台)cin标准输入对象(键盘)时,他们都被包含在<iostream>头文件中一个名为std的命名空间中,所以我们写C++代码#include <iostream>是为了包含C++的官方库,using namespace std是为了展开<iostream>中的std命名空间。

2. <<是流插入运算符,>>是流提取运算符

四、缺省参数

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

缺省值只能是常量或全局变量。

1、全缺省参数

void func(int a = 5, int b = 6, int c = 9)
{
	cout << a<< b << c << endl;
}
int main()
{
	func(1,2,3);//a接收1,b接收2,c接收3
	func(1,2);//a接收1,b接收2,c使用缺省值9
    fun();//a使用缺省值5,b使用缺省值6,c使用缺省值9
	return 0;
}

全缺省参数在调用时,不给参数时,将会使用缺省值调用。给参数时,实参和形参从左到右匹配。

2、半缺省参数

void func(int a , int b = 6, int c = 9)
{
	cout << a << b << c << endl;
}
int main()
{
	func(1, 2, 3);//a接收1,b接收2,c接收3
	func(1);//a接收1,b使用缺省值6,c使用缺省值9
	func();//错误写法,因为形参a不是缺省,至少传一个参数
	return 0;
}

未使用缺省值的形参,在传参时必须传入,有缺省值的形参,根据需要可传可不传。

1、缺省必须从右往左缺省,不能a变量给了缺省值,b没给,c给了,这种跳跃的缺省语法是不被允许的。

2、缺省参数不能在函数声明和定义中同时出现,当工程中有.h和.c时,在.h(声明)中给缺省值,定义中就不要给缺省值了!

五、函数重载

函数重载是函数的一种特殊情况,C++允许在同一作用域中声明多个同名函数,这些同名函数参数类型参数个数类型的顺序不同,常用来处理实现功能类似数据类型不同的问题。

1、参数类型不同

void Swap(int* a, int* b)
{
	;
}
void Swap(double* a, double* b)
{
	;
}

2、参数个数不同

void f()
{
	cout << 10 << endl;
}
void f(int a, int b)
{
	cout<<20<<endl;
}

3、类型顺序不同

void f(char b, int a)
{
	cout << 10 << endl;
}
void f(int a, char b)
{
	cout<<20<<endl;
}

注意,如果这里的两个参数的类型全是int,那么变量a和b交换位置,是不构成函数重载的。

4、函数重载的原理

为什么C语言不支持函数重载而C++支持呢?

在linux下,采用gcc编译完成后,函数名字的修饰没有发生改变。

而在g++的函数修饰后变成【_Z+函数长度 +函数名+类型首字母】。 在linux下,采用g++编译完成后,函数名字的修饰发生改变,编译器将函数参数类型信息添加到修改后的名字中,所以就能根据形参,来区分同名函数。

C语言没办法支持重载,因为同名函数没办法区分。而C++是通过函数名修饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持了重载。

5、为什么不能根据函数的返回值进行函数重载

错误的写法:

void f(int a, int b)
{
	cout << 10 << endl;
}
int f(int a, int b)
{
	cout<<20<<endl;
}

原因:根据函数重载的原理,函数名修饰规则只和形参有关,与返回值无关。

那么函数名修饰规则为什么不加上返回类型的区分用于函数重载?因为就算函数名修饰规则中有函数返回类型的区分,我们在调用函数传参的时候,编译器是没办法知道我们想要调用哪个函数。比如上方代码,我们调用f(1, 2)时,编译器无法区分我们调用哪个f()函数,所以不能根据函数的返回值进行函数重载。

六、引用

引用,就是已定义变量的一个别名。

可以给变量取别名,也可以给变量的别名取别名,编译器不会为引用额外开辟空间,他们都代表着同一块空间。

取的别名的类型必须与原变量保持一致。

1、引用特性

1.1引用在定义的时候必须初始化

1.2一个变量可以有多个引用

1.3一旦成为了某个变量的引用,引用将一直效忠这个变量

这里的代码中,ra是a的引用,那么ra就和a永久绑定了。ra=b是让b的值赋给ra,ra被修改成5,a也就变成了5。

2、常引用(指针和引用的赋值,权限可以缩小不能扩大)

2.1对常量的引用

int main()
{
	const int& a = 10;
	return 0;
}

因为10是常量,有“常属性”,可读不可写,如果不加const修饰,那么a的权限就变成了可读可写,这是权限的放大,语法是不通过的,所以这里的a必须加上const修饰。

2.2对const常量的引用

int main()
{
	const int a = 10;
	const int& ra = a;
	return 0;
}

因为a有const修饰,所以a的引用也必须有const修饰,做到权限平移。

2.3隐式、强制类型转换的引用

int main()
{
	double a = 10.256;
	const int& ra = a;//ra打印结果是10
	return 0;
}

这里将发生隐式类型转换,a将自身的数值截断后复制到一个tmp临时变量中,ra对tmp这个临时变量进行引用。临时变量具有常属性。所以这里要加const修饰。

2.4传参时的权限问题

1、ra是只读的,传参时,权限不能扩大为可读可写,这里时一个权限放大的错误。

我们在传参时,如果这个形参在函数中不会被修改,那我们可以无脑用const来修饰形参。

2、缺省引用,必须使用const修饰

3、const提升生命周期

Add函数的的返回值会先拷贝一份一模一样副本作为临时变量用于带回返回值,临时变量具有常属性,所以这里用const修饰,const修饰后,该临时变量的生命周期延长,编译器不会报错。

3、引用的使用场景

3.1引用做参数

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

引用作为函数的形参,函数将使用原始数据,而不是原始数据的临时拷贝。

引用做参数的优势

1、减少拷贝,提高效率

2、作为输出型参数,在函数中,形参改变会改变实参。

3、一般引用做参数的(函数中形参不需要改变)都要用const引用

3.2引用做返回值

错误用法:

int& Add(int a, int b)
{
	int sum = a + b;
	return sum;
}
int main()
{
	int ret = Add(1, 2);
	cout << ret << endl;
	return 0;
}

当Add函数调用完毕后,函数栈帧被销毁,同时通过临时变量将sum的别名返回,但是sum它已经被销毁了。所以这是一种错误的用法。

正确用法:

int& Add(int a, int b)
{
	static int sum = a + b;
	return sum;
}
int main()
{
	int ret = Add(1, 2);
	cout << ret << endl;
	return 0;
}

函数调用完毕后,栈帧销毁,同时通过临时变量将sum的别名返回,由于sum是静态的,所以不会出现上方例子的情况。

总结:函数栈帧结束后,如果返回值不会随着栈帧的结束而销毁,那么就可以使用引用返回。

引用返回相较于传值返回的优势

1、减少拷贝,提高运行效率

如图所示,传值返回是会生成一份返回值的临时拷贝的,这将会消耗空间同时降低运行效率。

而传引用返回也会生成一个临时变量,这个临时变量是sum的别名,它和sum共同表示同一块内容,传引用返回不会占用额外空间用于拷贝,提升运行效率。

2、可以直接对返回值进行修改

因为modify函数返回的是pos节点的引用,我们可以直接对这个引用进行修改操作。

3.3引用和指针的区别

1、语法上引用是变量的别名,不开空间,而指针存储一个变量地址。但是引用的底层是用指针实现的。

2、引用在定义时必须初始化,指针没有要求

3、引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体 。这就导致了C++的引用代替了一部分指针的功能,但不能完全代替。例如链表中的next必须用指针实现。如果采用引用的方式引用节点,插入删除节点要修改next,没办法通过引用改变next指向的值。

4、没有NULL引用,但有NULL指针

5、在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32

位平台下占4个字节)

6、引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小

7、有多级指针,但是没有多级引用

8、访问实体方式不同,指针需要显式解引用,引用编译器自己处理

9、引用比指针使用起来相对更安全

七、inline关键字

1、inline的概念

以inline修饰的函数是内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数调用建立函数栈帧的开销,能够提升程序运行的效率。一般用于语句简短的小函数当中。

2、inline修饰的函数的特点

1、inline修饰函数是一种以空间(编译出来的可执行程序的大小)换时间的方法。缺点时会使可执行程序变大,优点是没有函数调用建立函数栈帧的开销,能够提升程序运行的效率。

2、程序员用可以inline修饰函数,但是否让这个函数成为内联函数展开,由编译器决定。

3、内联用于修饰规模较小、非递归、频繁调用的函数。

4、内联函数声明和定义不要分离。一旦分离,编译器认为内联函数无需调用,程序走到编译这步时,内联函数的定义不会被汇总符号,程序再走到汇编阶段,单个文件进行符号表的汇总(这时函数定义文件没有该函数的符号,而声明文件中有声明的符号),程序再走到链接这一步,进行符号表的合并,编译器发现只有函数声明的符号,却找不到函数定义的符号,自然形成了链接错误。

3、宏的优缺点和替代

宏的优点:增强代码的复用性,执行速度比函数快

宏的缺点:无法调试,宏可读性差且难写,没有类型的安全检查

宏的替代:用const、enum定义常量,用inline修饰短小函数。

八、auto的用法

auto用于自动推导类型

注意auto不能做函数参数,因为类型不明。auto不能声明数组。

九、范围for

范围for用于遍历数组,依次取arr数组中的数据赋值给e,自动迭代到结束。

int main()
{
	int arr[] = { 1,2,3,4,5,6 };
    //遍历数组
	for (auto e : arr)
	{
		cout << e << " ";
	}
    //遍历并修改数组
	for (auto& e : arr)
	{
		cout << e * 2 << " ";
	}
		return 0;
}

注意范围for循环迭代的范围必须是确定的:

void func(int array[])
{
 ? ?for(auto& e : array)
 ? ? ? ?cout<< e <<endl; 
}

函数传参,传进来的不是数组是指针,for循环迭代范围不明。

十、关键字nullptr

在C++中NULL被定义为常量0,而不是指针类型。

#ifndef NULL
#ifdef __cplusplus
#define NULL ? 0
#else
#define NULL ? ((void *)0)
#endif
#endif

这样的话,传参可能会出现错误。

1. 在使用nullptr表示指针空值时,不需要包含头文件,因为nullptr是C++11作为新关键字引入 的。

2. 在C++11中,sizeof(nullptr) 与 sizeof((void*)0)所占的字节数相同。

3. 为了提高代码的健壮性,在后续表示指针空值时建议最好使用nullptr。?

?CSDN话题挑战赛第2期
参赛话题:学习笔记

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-09-24 20:38:17  更:2022-09-24 20:39:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 15:17:07-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码