C++基础语法之内联函数、auto关键字、范围for循环、nullptr

1. 内联函数

在讲内联函数之前我们先回忆一下C语言宏的概念,我们可以用宏定义一个函数,但是在使用的过程,会发现有以下缺点:

  1. 代码可读性差,因为优先级的关系,容易用错
  2. 不能调试
  3. 没有类型检查不安全

优点是:

  1. 提高了代码的复用性
  2. 因为不用开辟栈帧,所以提高了程序的性能

而我们C++之父则用内联函数替代宏定义函数,内联函数不仅有宏定义函数的优点还没有宏定义函数的缺点,可以说是无敌了。

1. 概念

inline修饰的函数叫做内联函数,编译时C++会在调用内联函数的地方展开(也不一定,后面来解释 ),不会开辟栈栈,提高了程序运行的效率。
眼见为实,我们通过汇编语言来看一下,是否展开了。
这里是普通函数,可以看到call调用了函数
在这里插入图片描述
这里我们使Add函数变成了内联函数,可以看到直接展开了
在这里插入图片描述

2. 特性

  1. 内联函数是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会用函数体替换函数调用。提高了效率但是使目标文件变大了。
  2. 内联函数只是对编译器的一个建议,不同编译器对内联函数的实现各有差异,所以编译器可以拒绝这个建议,这里就解释了上面说的可能不会展开内联函数,而是当做普通函数处理,一般建议:函数代码少(没有具体定义,取决于编译器)、不是递归、频繁调用的函数用inline修饰,否则编译器会拒绝这个请求。
  3. 内联函数不建议定义和声明分离,分离会导致链接错误,因为内联函数被展开,就没有函数地址,所以就会链接错误。
    在这里插入图片描述
    在这里插入图片描述

2. auto关键字

2.1 auto简介

在一些语言中,如:python等语言中,我们定义一个变量是不需要声明变量类型的,而是让编译器自己去推导,使得代码写起来更加的方便。所以C++11引入了auto关键字。

int main()
{
	int a = 0;
	auto b = a;
	auto c = &a;

	//typeid是用来识别变量类型的
	cout << typeid(b).name() << endl;
	cout << typeid(c).name() << endl;
	return 0;
}

在这里插入图片描述

2.2 使用规则

  1. auto和指针与引用结合起来用
    用auto声明指针类型的时候,用auto和auto*没有任何区别,但是用auto声明引用类型的时候必须加&
int main()
{
	int a = 0;
	auto b = a;
	auto c = &a;
	auto* d = &a;
	auto& e = a;

	//typeid是用来识别变量类型的
	cout << typeid(b).name() << endl;
	cout << typeid(c).name() << endl;
	cout << typeid(d).name() << endl;
	cout << typeid(e).name() << endl;
	return 0;
}

在这里插入图片描述

2.当在同一行定义多个变量时,这些变量的类型必须一样,否则编译器会报错,因为编译器只对第一个数据的类型进行推导,然后用推导出来的类型来定义其他变量。

int main()
{
	auto a = 1, b = 2.0;
	return 0;
}

在这里插入图片描述

2.3 auto不能用的场景

  1. auto不能做函数的参数
  2. auto不能用来申明数组
  3. 为了避免与C++98中的auto发生混淆,C++11只保留了auto作为类型指示符的用法
  4. 正常定义变量的时候一般不使用auto,auto在实际中最常见的优势用法就是跟范围for循环,还有lambda表达式等进行配合使用,还有冗长变量名。

3. 基于范围的for循环

3.1 普通for循环 vs 范围for循环

int main()
{
	int arr[] = { 1,2,3,4,5 };
	for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		cout << arr[i] << " ";
	}
	cout << endl;
	for (int* a = arr; a < arr + sizeof(arr) / sizeof(arr[0]); a++)
	{
		cout << *a << " ";
	}
	cout << endl;
	for (auto e : arr)
	{
		cout << e << " " ;
	}
	return 0;
}

在这里插入图片描述

可以看出,这几种遍历数组的方式都是可以的,但我们可以知道使用范围for,不用设置长度,避免了越界访问的问题,而且书写起来方便、简洁。

3.2 范围for的语法

for循环后的括号由冒号“ :”分为两部分:第一部分是范围内用于迭代的临时变量,第二部分则表示被迭代的范围。

int main()
{
	int array[] = { 1, 2, 3, 4, 5 };
	for (auto& e : array)
		e *= 2;
	for (auto e : array)
		cout << e << " ";
	return 0;
}

注:

  1. :前面的变量不是数组中的元素,而是临时拷贝,改变:前面的变量的值,数组中的值不会变,如果想要改变的话,用引用类型就行。
  2. 与普通循环类似,可以用continue来结束本次循环,也可以用break来跳出整个循环。

3.3 范围for的使用条件

  1. 迭代的范围必须明确
void Test(int array[])
{
	for (auto& e : array)
		e *= 2;
	for (auto e : array)
		cout << e << " ";
}
int main()
{
	int array[] = { 1, 2, 3, 4, 5 };
	Test(array);
	return 0;
}

在这里插入图片描述
因为这里传过去的是指针,确定不了数组的范围。

  1. 迭代的对象要实现++和==的操作。

4. 指针空值nullptr

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

该程序的目的是想通过f(0)调用void f(int),通过f(NULL)调用void f(int*),但运行结果和我们的想法却不一样。
在这里插入图片描述
这是为什么呢?其实NULL的本质就是宏,在传统的C头文件(stddef.h)中,可以看到如下代码。

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

可以看到,NULL可能被定义为字面常量0,或者被定义为无类型指针(void*)的常量。在C++98中,字面常量0既可以是一个整形数字,也可以是无类型的指针(void*)常量,但是编译器默认情况下将其看成是一个整形常量,如果要将其按照指针方式来使用,必须对其进行强转(void*)0。

所以C++引入nullptr关键字表示空指针,为了提高代码的健壮性,在后续表示指针空值时建议最好使用nullptr,使用该关键字不需要头文件。

void f(int)
{
	cout << "f(int)" << endl;
	return;
}
void f(int*)
{
	cout << "f(int*)" << endl;
	return;
}
int main()
{
	f(0);
	f(nullptr);
	return 0;
}

在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
AutoHotkey中,循环可以通过使用loop命令或while命令来实现。引用中给出了使用loop命令的示例代码,其中循环会一直执行,直到用户释放了F1键。在循环内部,首先检查F1键是否被释放,如果是,则中断循环;否则,继续执行点击鼠标的操作。最后,通过return语句来结束函数。 另一种循环方法是使用while命令,在循环条件中使用GetKeyState函数来判断F1键是否被按住。只要F1键被按住,循环就会继续执行点击鼠标的操作。当F1键被释放时,循环停止执行,并通过return语句结束函数。需要注意的是,这里的while循环是一个无限循环,只有在循环内部的条件判断中才会决定是否继续执行。 所以,autohotkey中的循环可以使用loop命令或while命令来实现,具体使用哪种方式取决于需求和代码的逻辑。<span class="em">1</span><span class="em">2</span> #### 引用[.reference_title] - *1* [autohotkey循环](https://blog.csdn.net/qq_38619183/article/details/83211041)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [AutoHotkey如何循环读取ini文件里所有section的所有key值](https://blog.csdn.net/wbryfl/article/details/51442552)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值