初遇C++之语法篇(完结)

这篇具有很好参考价值的文章主要介绍了初遇C++之语法篇(完结)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

🧃博客主页:阿博历练记
📖文章专栏:c++
🚍代码仓库:阿博编程日记
🍡欢迎关注:欢迎友友们点赞收藏+关注哦🌹

初遇C++之语法篇(完结),C++,c++,开发语言

🍭1.函数重载

📜1.1函数重载的概念

函数重载:是函数的一种特殊情况,C语言不允许同名函数,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 类型类型顺序)不同,🚩🚩友友们注意这里不比较返回值常用来处理实现功能类似数据类型不同的问题.

1.参数类型不同

#include<iostream>
using namespace std;
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;
}
int main()
{
	cout << Add(1, 2) << endl;
	cout << Add(1.1, 2.2) << endl;
	return 0;
}

初遇C++之语法篇(完结),C++,c++,开发语言

2.参数个数不同

#include<iostream>
using namespace std;
void f()
{
	cout << "f()" << endl;
}
void f(int a)
{
 cout << "f(int a)" << endl;
}
int main()
{
	f();
	f(10);
	return 0;
}

初遇C++之语法篇(完结),C++,c++,开发语言
3.参数类型顺序不同

#include<iostream>
using namespace std;
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()
{
	f(10, 'a');
	f('a', 10);
	return 0;
}

初遇C++之语法篇(完结),C++,c++,开发语言

📢1.2函数重载三大误区

❌误区一:

#include<iostream>
using namespace std;
void f(int a, char b)
{
	cout << "f(int a,char b)" << endl;
}
void f(int b, char a)
{
	cout << "f(int b, char a)" << endl;
}
int main()
{
	f(10, 'a');
	f('a', 10);
	return 0;
}

初遇C++之语法篇(完结),C++,c++,开发语言

📝友友们注意,函数重载是类型顺序不同,而不是形参的名字顺序不同.

❌误区二:

#include<iostream>
using namespace std;
namespace  N1
{
	void func(int x)
	{

	}
}
namespace  N2
{
	void func(double x)
	{

	}
}
int main()
{
	return 0;
}

初遇C++之语法篇(完结),C++,c++,开发语言

#include<iostream>
using namespace std;
namespace  N1
{
	void func(int x)
	{

	}
}
namespace  N2
{
	void func(int x)
	{

	}
}
int main()
{
	return 0;
}

初遇C++之语法篇(完结),C++,c++,开发语言

🕵可能友友们会认为第①种构成函数重载,但是如果第一种构成重载的话,现在第②种很显然已经不是函数重载了,为什么程序还是可以编译通过呢,所以我们这里就可以从反面验证这里不构成函数重载,这里主要就是这两个函数不在同一个作用域里面,而函数重载要求在同一个作用域里面.

❌误区三:

#include<iostream>
using namespace std;
void Func(int a)
{
	cout << "void Func(int a)" << endl;
}
void Func(int a,int b=10)
{
	cout << "void Func(int a,int b)" << endl;
}
int main()
{
	/*Func(1);
	Func(1, 2);*/
	return 0;
}

初遇C++之语法篇(完结),C++,c++,开发语言

💨💨友友们注意,这里构成函数重载,因为这两个函数参数的个数不同,与缺省参数没有关系.

#include<iostream>
using namespace std;
void Func(int a)
{
	cout << "void Func(int a)" << endl;
}
void Func(int a,int b=10)
{
	cout << "void Func(int a,int b)" << endl;
}
int main()
{
	Func(1);
	Func(1, 2);
	return 0;
}

初遇C++之语法篇(完结),C++,c++,开发语言

🌟🌟虽然它们构成重载函数,但是在调用的时候会存在歧义,比如当实参只有1时,这两个函数都可以调用,编译器就不知道该调用谁了,所以就会产生调用不明确的报错.

🍄1.3C++支持函数重载的原理–名字修饰

初遇C++之语法篇(完结),C++,c++,开发语言
① C语言程序
初遇C++之语法篇(完结),C++,c++,开发语言
② C++程序

1.vs2022环境下
初遇C++之语法篇(完结),C++,c++,开发语言
2.Linux环境下
初遇C++之语法篇(完结),C++,c++,开发语言

🍧2.引用

📜2.1引用概念

引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间,🔍引用类型必须和引用实体是同种类型的.

🪄2.2引用使用场景:

一.引用做参数

引用示例1:

1.传址交换

#include<iostream>
using namespace std;
void swap(int*x1,int*x2)
{
	int tmp = *x1;
	*x1 = *x2;
	*x2 = tmp;
}
int main()
{
	int a = 3;
	int b = 5;
	swap(&a, &b);
	cout << a << endl;
	cout << b << endl;
	return 0;
}

2.引用交换

#include<iostream>
using namespace std;
void swap(int&x1,int&x2)
{
	int tmp = x1;
	x1 = x2;
	x2 = tmp;
}
int main()
{
	int a = 3;
	int b = 5;
	swap(a, b);
	cout << a << endl;
	cout << b << endl;
	return 0;
}

所以友友们当我们使用引用之后,就可以不用指针了,因为x1就是a的别名,x2就是b的别名,所以它们两个就是a和b,我们只需要直接交换就可以了🤩🤩.

引用示例2:

1.二级指针

#include<iostream>
#include<stdlib.h>
using namespace std;
typedef struct
{
	int val;
	struct ListNode* next;
}ListNode;
void PushBack(ListNode**pphead,int x)
{
	ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
	newnode->val = x;
	newnode->next = NULL;
	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	else
	{
		//...
	}
}
int main()
{
	ListNode* plist = NULL;
	PushBack(&plist, 1);
	PushBack(&plist, 2);
	PushBack(&plist, 3);
	PushBack(&plist, 4);
	return 0;
}

💬💬友友们对于这种情况,在我们没有使用引用之前,我们必须使用传址的方式,用二级指针接收,然后解引用才能改变plist,如果用一级指针接收的话,那么形参就是实参的一份临时拷贝,形参的改变不会影响实参,所以友友们这种方法是不是比较麻烦.🤦🤦

2.引用交换

#include<iostream>
#include<stdlib.h>
using namespace std;
typedef struct
{
	int val;
	struct ListNode* next;
}ListNode;
void PushBack(ListNode*&phead,int x)
{
	ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
	newnode->val = x;
	newnode->next = NULL;
	if (phead == NULL)
	{
		phead = newnode;
	}
	else
	{
		//
	}
}
int main()
{
    ListNode* plist = NULL;
	PushBack(plist, 1);
	PushBack(plist, 2);
	PushBack(plist, 3);
	PushBack(plist, 4);
	return 0;
}

💌友友们这里phead就是plist的别名,所以它就是plist,所以改变phead就是改变plist,学完引用之后我们这里就可以不再用二级指针了.💯

二.引用做返回值

1.传值返回

#include<iostream>
#include<stdlib.h>
using namespace std;
int count()
{
    int n = 0;
	n++;
	// ...
	return n;
}
int main()
{
	int ret = count();
	return 0;
}

2.传引用返回

#include<iostream>
#include<stdlib.h>
using namespace std;
int& count()
{
    int n = 0;
	n++;
	// ...
	return n;
}
int main()
{
	int ret = count();
	//这里打印可能是1,也可能是随机值
	cout << ret << endl;
	return 0;
}

初遇C++之语法篇(完结),C++,c++,开发语言
代码验证

#include<iostream>
#include<stdlib.h>
using namespace std;
int& count()
{
    int n = 0;
	n++;
	// ...
	return n;
}
int main()
{
	int &ret = count();
	//这里返回值可能是1,也可能是随机值
	cout << ret << endl;
	cout << ret << endl;
	return 0;
}

初遇C++之语法篇(完结),C++,c++,开发语言

🍔知识小结:如果函数返回时,出了函数作用域,如果返回对象还在(还没还给系统),则可以使用引用返回,如果已经还给系统了,则必须使用传值返回。

🔍2.3引用特性

1.引用必须在定义的时候初始化.
2.一个变量可以有多个引用,比如这里b,c,d都是a的引用.
初遇C++之语法篇(完结),C++,c++,开发语言
3.引用一旦引用一个实体,再不能引用其它实体.
初遇C++之语法篇(完结),C++,c++,开发语言

🧊2.4常引用

#include<iostream>
#include<stdlib.h>
using namespace std;
int main()
{
	const int a = 0;
	int x = 1;
	int& b = a;          //权限的放大
	const int& c = a;    //权限的平移
	const int& d = x;   //权限的缩小
	return 0;
}

📝友友们在引用过程中,权限可以平移缩小,但是不能放大.

🎃经典误区

误区①

#include<iostream>
#include<stdlib.h>
using namespace std;
int main()
{
	const int a = 0;
	int b = a;
	return 0;
}

📝这里b是a的赋值,把a的值拷贝给b,b的改变不会影响a,它和a根本不是一个变量,所以不涉及权限的放大.

误区②

#include<iostream>
#include<stdlib.h>
using namespace std;
int main()
{
	int i = 0;
	double& d = i;
	return 0;
}

🔔友友们这里注意,i是int类型,d是double类型,当i赋值给d时,这里会有隐式类型转换,这里会产生一个double类型的临时变量,临时变量具有常性不能修改,所以这里实质上是一种权限的放大,所以我们应该加一个const保持权限的平移才可以.

误区③

#include<iostream>
#include<stdlib.h>
using namespace std;
int func()
{
    int a = 0;
	return a;
}
int main()
{
	int& ret = func();
	return 0;
}

👑友友们注意这里是传值返回,这里不是用变量a返回,这里会生成一个临时变量,用临时变量返回然后再拷贝给ret,临时变量具有常性,不能修改,所以我们这里在引用的时候实质上也是权限的放大,所以我们要加上const保持权限的平移就可以了.

💌面试提问

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

🥷3.内联函数

📜3.1内联函数的概念

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

1.未用inline
初遇C++之语法篇(完结),C++,c++,开发语言
2.使用inline

🔎查看方式

1. 在release模式下,查看编译器生成的汇编代码中是否存在call Add
2.在debug模式下,需要对编译器进行设置,否则不会展开(因为debug模式下,编译器默认不会对代码进行优化,以下给出vs2013的设置方式)

初遇C++之语法篇(完结),C++,c++,开发语言
初遇C++之语法篇(完结),C++,c++,开发语言

📑3.2内联函数的特性

1. inline是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会用函数体替换函数调用缺陷:可能会使目标文件变大,导致代码膨胀。优势:少了调用开销,提高程序运行效率。
初遇C++之语法篇(完结),C++,c++,开发语言
2 inline对于编译器而言只是一个建议,不同编译器关于inline实现机制可能不同,一般建议:将函数规模较小(即函数不是很长,具体没有准确的说法,取决于编译器内部实现)、不是递归、且频繁调用的函数采用inline修饰,否则编译器会忽略inline特性.
3.inline不建议声明和定义分离,分离会导致链接错误。因为内联函数在调用的时候就展开了,所以编译器就没有生成函数的地址,所以在链接的时候就会找不到。

👻4.auto关键字

📜4.1auto简介

C++11中,标准委员会赋予了auto全新的含义即:auto不再是一个存储类型指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期推导而得。
注意:使用auto定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导auto的实际类型。因此auto并非是一种“类型”的声明,而是一个类型声明时的“占位符”,编译器在编译期会将auto替换为变量实际的类型。

#include<iostream>
#include<stdlib.h>
#include<vector>
#include<string>
using namespace std;
int main()
{
	int a = 0;
	auto b = a;
	auto c = &a;                  //普通场景没有价值,类型很长时很有价值,可以简化我们的代码
	auto& d = a;
	std::vector<std::string> v;
	std::vector<std::string>::iterator it = v.begin();
	auto it = v.begin();
	return 0;
}

友友们,这里我们也可以通过typeid看它们的类型🔍

int main()
{
	int a = 0;
	auto b = a;
	auto c = &a;                  //普通场景没有价值,类型很长时很有价值,可以简化我们的代码
	auto& d = a;
	std::vector<std::string> v;
	//std::vector<std::string>::iterator it = v.begin();
	auto it = v.begin();
	cout << typeid(b).name() << endl;
	cout << typeid(c).name() << endl;
	cout << typeid(it).name() << endl;
	return 0;
}

初遇C++之语法篇(完结),C++,c++,开发语言

🔖4.2auto不能推导的场景

1. auto不能作为函数的参数
void TestAuto(auto a)
{} ,此处代码编译失败,auto不能作为形参类型,因为编译器无法对a的实际类型进行推导,比如我们实参传了一个3,编译器无法判断是整形3还是字符3.
2.auto不能直接用来声明数组
auto b[] = {4,5,6}; 这种情况也是不允许的,编译器也无法判断类型.

📔5.基于范围的for循环(C++11)

#include<iostream>
#include<stdlib.h>
using namespace std;
int main()
{
	int array[] = { 1, 2, 3, 4, 5 };
	for (int i = 0; i < sizeof(array) / sizeof(array[0]); ++i)
		array[i] *= 2;
	for (int i = 0; i < sizeof(array) / sizeof(array[0]); ++i)
		cout << array[i] << " ";
	cout << endl;
	for (auto e: array)
	{
		cout << e << " ";
	}
	cout << endl;
	return 0;
}

初遇C++之语法篇(完结),C++,c++,开发语言

🃏范围for循环会依次取数组中的数据赋值给e,自动判断结束,自动迭代.

初遇C++之语法篇(完结),C++,c++,开发语言

友友们,这里我们对x乘以2,为什么打印出来的数据还是没有变化呢,🚩这里一定要注意,x是数组数据的拷贝,x的改变不会影响数组中的数据,所以我们需要加一个引用就可以了,此时x就是数组中数据的别名,就是数组中的数据,所以此时x的改变就会影响数组中的元素了.

❌误区

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

友友们,这种是不可以的,当使用范围for循环的时候,array那里必须是数组名,C++实际上只把形参数组名作为一个指针变量来处理,用来接收从 实参传过来的地址.

🎨6.指针控制nullptr(C++11)

using namespace std;
void f(int)
{
	cout << "f(int)" << endl;
}
void f(int*)
{
	cout << "f(int*)" << endl;
}
int main()
{
	f(0);
	f(NULL);
	f((int*)NULL);
	return 0;
}

初遇C++之语法篇(完结),C++,c++,开发语言

友友们注意,在C++中,NULL的类型就不是指针类型了,我们如果要当成指针使用的话,需要强转类型
注意:
1.在C++中引入了一个关键字nullptr,在使用nullptr表示指针空值时,不需要包含头文件
2. 在C++11中,sizeof(nullptr) 与 sizeof((void*)0)所占的字节数相同。
3.为了提高代码的健壮性,在后续表示指针空值时建议最好使用nullptr

✨✨好了友友们,这期的内容到这里就告一段落了,下期不见不散.🪄🪄文章来源地址https://www.toymoban.com/news/detail-632616.html

到了这里,关于初遇C++之语法篇(完结)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • “C++基础入门指南:了解语言特性和基本语法”

    C++是在C的基础之上,容纳进去了面向对象编程思想,并增加了许多有用的库,以及编程范式 等。熟悉C语言之后,对C++学习有一定的帮助 工作之后,看谁的技术牛不牛逼,不用看谁写出多牛逼的代码,就代码风格扫一眼,立刻就能看出来是正规军还是野生的程序员。代码的风

    2024年02月16日
    浏览(40)
  • c++:基于c语言基础上的语法不同(1)

    前言:此篇文章适合学完c语言基础概念的同学,是帮助c向c++语言的同学快速掌握基本语法。 按照c语言的语法也可以,头文件多包含#includestring 下面是通过数组名的方法打印字符串hello world。 1e2就是1x10的二次方 1e-2就是1x10的负二次方 float类型后面的数字要多写一个f,不然编

    2024年01月20日
    浏览(40)
  • 【鸿蒙开发】第七章 ArkTS语言UI范式-基础语法

    通过前面的章节,我们基本清楚鸿蒙应用开发用到的语言和项目基本结构,在【鸿蒙开发】第四章 Stage应用模型及项目结构也提到过ArkTS的UI范式的 基本语法 、 状态管理 、 渲染控制 等能力,简要介绍如下: 基本语法 : ArkTS 定义了 声明式UI描述 、 自定义组件 和 动态扩展

    2024年02月03日
    浏览(64)
  • HarmonyOS/OpenHarmony应用开发-ArkTS语言基本语法说明

    图1  示例效果图   本示例中,ArkTS的基本组成如下所示。 图2  ArkTS的基本组成     装饰器: 用于装饰类、结构、方法以及变量,并赋予其特殊的含义。如上述示例中@Entry、@Component和@State都是装饰器,@Component表示自定义组件,@Entry表示该自定义组件为入口组件,@State表示组

    2024年02月07日
    浏览(55)
  • HarmonyOS学习路之方舟开发框架—学习ArkTS语言(基本语法 三)

    在开始之前,先明确自定义组件和页面的关系: 自定义组件: @Component 装饰的 UI 单元,可以组合多个系统组件实现 UI 的复用。 页面:即应用的 UI 页面。可以由一个或者多个自定义组件组成, @Entry 装饰的自定义组件为页面的入口组件,即页面的根节点,一个页面有且仅能有

    2024年02月16日
    浏览(63)
  • HarmonyOS学习路之方舟开发框架—学习ArkTS语言(基本语法 五)

    如果每个组件的样式都需要单独设置,在开发过程中会出现大量代码在进行重复样式设置,虽然可以复制粘贴,但为了代码简洁性和后续方便维护,我们推出了可以提炼公共样式进行复用的装饰器@Styles。 @Styles装饰器可以将多条样式设置提炼成一个方法,直接在组件声明的位

    2024年02月17日
    浏览(56)
  • HarmonyOS学习路之方舟开发框架—学习ArkTS语言(基本语法 二)

    在ArkUI中,UI显示的内容均为组件,由框架直接提供的称为系统组件,由开发者定义的称为自定义组件。在进行 UI 界面开发时,通常不是简单的将系统组件进行组合使用,而是需要考虑代码可复用性、业务逻辑与UI分离,后续版本演进等因素。因此,将UI和部分业务逻辑封装成

    2024年02月04日
    浏览(54)
  • HarmonyOS学习路之方舟开发框架—学习ArkTS语言(基本语法 四)

    当创建了自定义组件,并想对该组件添加特定功能时,例如在自定义组件中添加一个点击跳转操作。若直接在组件内嵌入事件方法,将会导致所有引入该自定义组件的地方均增加了该功能。为解决此问题,ArkUI引入了@BuilderParam装饰器,@BuilderParam用来装饰指向@Builder方法的变量

    2024年02月17日
    浏览(53)
  • HarmonyOS学习路之方舟开发框架—学习ArkTS语言(基本语法 一)

    ArkTS是HarmonyOS优选的主力应用开发语言。ArkTS围绕应用开发在 TypeScript (简称 TS )生态基础上做了进一步扩展,继承了 TS 的所有特性,是 TS 的超集。因此,在学习 ArkTS 语言之前,建议开发者具备 TS 语言开发能力。 当前, ArkTS 在 TS 的基础上主要扩展了如下能力: 基本语法:

    2024年02月16日
    浏览(72)
  • HarmonyOS(二)—— 初识ArkTS开发语言(下)之ArkTS声明式语法和组件化基础

    通过前面ArkTS开发语言(上)之TypeScript入门以及ArkTS开发语言(中)之ArkTS的由来和演进俩文我们知道了ArkTS的由来以及演进,知道了ArkTS具备了声明式语法和组件化特性,今天,搭建一个可刷新的排行榜页面。在排行榜页面中,使用循环渲染控制语法来实现列表数据渲染,使

    2024年02月04日
    浏览(58)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包