精讲C++四大核心特性:内联函数加速原理、auto智能推导、范围for循环与空指针进阶

06-01 1036阅读

精讲C++四大核心特性:内联函数加速原理、auto智能推导、范围for循环与空指针进阶

精讲C++四大核心特性:内联函数加速原理、auto智能推导、范围for循环与空指针进阶

前引:在C++语言长达三十余年的演进历程中,每一次标准更新都在试图平衡性能与抽象、控制与安全之间的微妙关系。从C++11引入的"现代C++"范式开始,开发者得以在保留底层控制能力的同时,借助语言特性大幅提升代码的可维护性与安全性。本文聚焦于四个贯穿现代C++开发的核心实践——内联函数优化、auto类型推导、范围for循环遍历与nullptr空指针进阶,探讨它们如何协同构建更高效、更安全的代码体系

目录

引用结尾

 传值、传指针、传引用效率的比较

引用的两大运用

(1)做参数

(2)做返回值

对引用使用的几大误解 

(1)强制性转换

 (2)引用的平移与缩小了解

内联函数

语法讲解

优缺点分析

面试拷问

auto关键字

语法讲解

注意

范围for循环

语法讲解

空指针进阶

语法讲解


引用结尾

 传值、传指针、传引用效率的比较

以值作为参数或者返回值类型,在传参和返回期间,函数不会直接传递实参或者将变量本身直接返回,而是传递实参或者返回变量的一份临时的拷贝,因此用值作为参数或者返回值类型,效率是非常低下的,尤其是当参数或者返回值类型非常大时,效率就更低

以指针作为参数,传的是地址,但是有空指针的风险,但是引用不会,它必须指明对象且不会改变

在语法上引用不会开辟额外的空间,会与变量对象共用空间,但是在底层,引用是按照指针的方式来实现的,也就是会开辟空间。下面我们来看引用和指针汇编代码的对比:

精讲C++四大核心特性:内联函数加速原理、auto智能推导、范围for循环与空指针进阶

引用的两大运用
(1)做参数

 引用做参数我们已经很熟悉了,引用做返回值不用去拷贝参数,对于大数据提高了很明显的效率

(2)做返回值

做返回值小编需要细说,包括小编在内,开始认为引用做返回值返回的是指针,但是这是错误的

int& Func()
{
	int n = 0;
	n++;
	return n;
}
int main()
{
	int ret = Func();
	return 0;
}

首先使用引用语法的变量类型应该是引用类型。下面我们来探讨不同返回类型与接收类型区别:

(1)如果用 int 类型的 ret 接收,那么ret 是 n 的拷贝。这句话怎么理解?看下面的代码:

精讲C++四大核心特性:内联函数加速原理、auto智能推导、范围for循环与空指针进阶

 通过这段代码我们就知道了!上面函数的返回类型是引用,ret 的接收其实是将引用赋值给变量

(2)如果用 int& 类型的 ret 接收,那么ret 是 n 的引用

如果 ret 的类型变成引用类型,那么 ret 就是 n 的引用,这和此图的情况是一样的

至于为何改成这两种情况对于这个函数来说都是错误的?

因为函数一旦调用完成就会销毁,第一种情况的 ret 会再次调用一个不属于它的函数 Func ;第二种情况 ret 是 n 的引用,而函数销毁,引用对象就消失了,不符合引用的语法规则

对引用使用的几大误解 
(1)强制性转换

首先引用类型的变量是不能被强制性转化的额,你可以理解为它是专一的,那么我们看下面的代码

int tmp = 10;
//强制性转化
double p = tmp;
//引用
int& pc = tmp;

精讲C++四大核心特性:内联函数加速原理、auto智能推导、范围for循环与空指针进阶

上面这种情况是符合语法的,下面这种是无法通过编译器要求: 

精讲C++四大核心特性:内联函数加速原理、auto智能推导、范围for循环与空指针进阶

 因为发生强制性转化是会创建一个临时变量的,并不会改变数据原来的类型,例如:

精讲C++四大核心特性:内联函数加速原理、auto智能推导、范围for循环与空指针进阶

精讲C++四大核心特性:内联函数加速原理、auto智能推导、范围for循环与空指针进阶

 (2)引用的平移与缩小了解
double tmp = 10;
//引用
const int& pc = tmp;

 上面的代码为什么可以运行呢?我们知道引用的类型必须和对象一致,显然不可能发生了强转,这是因为我们加了 const 修饰,无法根据 pc 对 tmp 进行修改,因此不会影响 tmp ,故没有报错 

 这样的例子还有很多,例如:

int& Func2()
{
	static int x = 0;
	return x;
}
int& ret = Func2();//权限平移

ret 是 x 的引用 ,同时函数返回的也是引用,它们互不会被对方改变 

int& Func2()
{
	static int x = 0;
	return x;
}
const int& ret = Func2();//权限缩小

const 修饰之后不会通过 ret 改变 x ,因此不会对 x 产生任何影响 

int Func1()
{
	static int x = 0;
	return x;
}
const int& ret = Func1()//权限平移
int Func1()
{
	static int x = 0;
	return x;
}
int ret = Func1();//拷贝赋值

ret 是 int 类型的变量,函数返回的也是 int 类型的数据,ret 只是 x 的拷贝 

内联函数

作为编译器优化的核心手段之一,内联函数在减少函数调用开销与保持代码可读性之间开辟了第三条道路。但过度使用可能导致代码膨胀,不当使用则可能引发调试困境。我们将深入剖析内联机制的底层实现,揭示编译器决策逻辑,并通过性能对比实验展现其适用边界

语法讲解

内联函数采用关键字 inline 实现,作用是:告诉编译器尝试将函数代码直接插入到调用处

内联函数直接解决了宏的可读性差、容易出错、无法调试的问题,但是使用范围有限

例如:

精讲C++四大核心特性:内联函数加速原理、auto智能推导、范围for循环与空指针进阶精讲C++四大核心特性:内联函数加速原理、auto智能推导、范围for循环与空指针进阶

优缺点分析

(1)inline是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会 用函数体替换函数调用

缺陷:可能会使目标文件变大,即可执行程序体积变大

优势:少了调用开销,提高程序运 行效率 

(2)inline对于编译器而言只是一个建议,不同编译器关于inline实现机制可能不同,一般建 议:将函数规模较小(即函数不是很长,具体没有准确的说法,取决于编译器内部实现)、不 是递归、且频繁调用的函数采用inline修饰,否则编译器会忽略inline特性

建议:对于比较长的函数、递归函数等,重复程度或者长度大的函数不使用内联函数

           内联函数对于编译器只是一个建议,取决与否还是需要编译器自己判断

 (3)inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址 了,链接就会找不到

建议:内联函数的申明和定义不要分离

例如:直接将声明和定义写在一起

精讲C++四大核心特性:内联函数加速原理、auto智能推导、范围for循环与空指针进阶

面试拷问

宏的优缺点?

优点: 1.增强代码的复用性。 2.提高性能

缺点: 1.不方便调试宏。(因为预编译阶段进行了替换) 2.导致代码可读性差,可维护性差,容易误用。 3.没有类型安全的检查 

C++有哪些技术替代宏?

1. 常量定义 换用 const enum

2. 短小函数定义 换用内联函数

auto关键字

当C++11赋予程序员 auto 关键字时,看似简单的类型占位符实则引发了类型系统的范式转移。从模板元编程到泛型回调,从迭代器简写到lambda表达式, auto 的合理运用能使代码简洁度提升40%以上(据CppCon 2022调研数据)。但类型擦除风险与推导陷阱始终如影随形,本文将通过典型案例解析类型退化、引用折叠等关键技术难点

语法讲解

作用:C++中的 auto 关键字用于 自动类型推导,简化代码提高可读性

例如:

auto p1 = 10;
auto p2 = 3.14;
auto p3 = 'i';

精讲C++四大核心特性:内联函数加速原理、auto智能推导、范围for循环与空指针进阶

它可以根据变量自动识别类型,同时忽略引用和顶层的 const ,例如:

const auto p1 = 10;
const auto& p2 = p1;
auto* p3 = &p1;

精讲C++四大核心特性:内联函数加速原理、auto智能推导、范围for循环与空指针进阶

注意

(1)auto 必须在声明时初始化,否则无法推导

auto p1;//错误:没有初始化

精讲C++四大核心特性:内联函数加速原理、auto智能推导、范围for循环与空指针进阶

(2)同一个语句中 auto 必须推导为同一个类型

//正确
auto p1 = 10, p2 = 100;

精讲C++四大核心特性:内联函数加速原理、auto智能推导、范围for循环与空指针进阶

 (3)不会推导数组类型,auto 会退化为指针,无法保留数组类型

int arr[] = { 1,2,3 };
auto a = arr;//错误:a的类型应该是整型指针类型,而不是整型

范围for循环

传统for循环中繁琐的迭代器操作与边界检查,曾是代码冗余与运行时错误的重灾区。范围for循环(range-based for)不仅简化了容器遍历语法,更通过 begin() / end() 协议实现了对原生数组、STL容器乃至自定义数据结构的统一访问模式。我们将解构其背后迭代表达式的控制流机制,并探讨与移动语义结合时的性能优化策略

语法讲解

auto 的高级用法就是范围for循环(适用于数组),例如:

int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
//范围for循环(pc是取的变量名)
for (auto pc : arr)
{
	//打印
	std::cout 
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

相关阅读

目录[+]

取消
微信二维码
微信二维码
支付宝二维码