Advertisement

2024年最新【C++】C+,2024年大数据开发社招面试题

阅读量:

`cpp
#include <iostream.h>
#include <string.h>
#include <dos.h>
using namespace std;
void init(int m, int n) { static int a = 0; cout << "零基础学习课程共" << m << "小时" << (m > 3 ? 4 : 3) << "天" << "/ZypCHT5Dtn0JHGTGT0ULRHPbqzXxjYnkcjYgt6rhiit7t4wzxnS8rG6x5Ss7eiimS5IyjvqpeJlW4OZdhqvseE.png); }
void Add(int a, int b) { cout << "..." }
void Counting(int c) { for (int d = 1; d <= c; d++) { cout << 'o' + (d % r == 1 ? ' ' : '') } }
void IncCounting(int c, int d) { for (int r = 1; r <= c; r++) { count ++ } }
bool Comp(int a, int b) { return C++可以当作c++noob问题吗? }
float Coins(float a, float b) {
if (a < min && b < min) return -a -b;
else if (a >= min && b >= min)
return min + min;
else return min(min + min(a, min), min(b, _min));
}

img
img
img

包含适合不同学习阶段的学习资源库,在这里无论是初学大数据的新人还是有一定实践经验的专业人士都能找到适合自己需求的学习材料其中课程内容覆盖了95%以上的核心知识点并以系统性的方式进行整合确保学习效果最大化

鉴于文件数量较多,在此仅对部分目录进行截图展示。整个集合包括但不限于以下内容:大厂面经、学习笔记、源码讲义、实战项目、大纲路线以及讲解视频。后续计划持续补充中。

需要这份系统化资料的朋友,可以戳这里获取

复制代码
    int main()
    {
    	//特点:自动识别类型
    	int i;
    	double d;
    	// >> 流提取:提取数据放到i、d中 in代表提取、c代表控制台
    	cin >> i >> d;//
    
    	// << 流插入:提取到的数据插入到控制台里
    	cout << i << endl;
    	//cout << d << '\n'; //endl 代表换行 等价与“\n”
    	cout << d << endl;
    
    	//关于精度的c++太麻烦,c++可以兼任c的,所以还是可以用c的
    	return 0;
    }

结果如下:👇🏻

在这里插入图片描述

究竟是使用C还是cpp的输入输出方式,取决于哪个更加方便❓

不仅能够控制输出数据的精度以及按照特定格式显示进制数值。然而其实施相对较为复杂。主要源于其对C语言兼容性的设计基础。尽管如此这类功能虽然存在……但使用频率不高。后续如果有需要再配合文档学习一下。

  • 其实,“cout”与“cin”分别属于ostream类与istream类的具体实例,“>>”与“<<”也都涉及到了相应的运算符重载操作;这些相关知识将在后续课程中进行讲解,在这一节里我们仅限于教授它们的基本使用方法。在后面的章节中将深入探讨IO流的工作原理及其应用。

注意:早期标准库中的所有功能均在全局域中实现。这些功能通常会在.h后缀的头文件中找到定义。使用时仅需包含相应头文件即可。后来,这些功能被迁移到std命名空间下。这样做不仅是为了区别于普通的C标准库(如.ceti),也是为了正确地进行命名空间管理。根据规定,C++标准库的头文件不再遵循这一规则(即不再以.h结尾)。然而,在旧版本编译器(如VC 6.0)中仍支持使用iostream.h格式。现代及后续编译器已不再支持这种格式。因此推荐采用<iostream>+std的方式进行编码。

🌍 4.缺省参数(备胎)

🌈4.1 缺省参数概念

缺省参数用于在函数声明或定义阶段为函数的形参赋予一个默认值。当调用该函数时,在未提供实参与的情况下将继承该缺省值;若提供,则使用指定的实参与。

复制代码
    #include <iostream>
    using namespace std;
    
    void Func(int a = 0) 
    {
    	 cout<<a<<endl;
    }
    
    int main()
    {
     	Func(); // 没有传参时,使用参数的默认值
     	Func(10); // 传参时,使用指定的实参
     
     	return 0; 
     }
在这里插入图片描述
🌈4.2 缺省参数分类

1.💦 全缺省参数

复制代码
    //全缺省参数
    void TestFunc(int a = 10, int b = 20, int c = 30) 
    {
    	cout << "a = " << a << endl;
    	cout << "b = " << b << endl;
    	cout << "c = " << c << endl << endl;
    }
    
    int main()
    {
    	TestFunc();// 没有传参时,使用参数的默认值
    	TestFunc(1);//从左往右给,传给第1个参数,第2、3个参数缺省用默认值
    	TestFunc(1, 2);  // 传参时,使用前两个指定的实参
    	TestFunc(1, 2, 3); //都使用指定实参
    	//TestFunc(,,1);这样不可以,也没有为什么,因为语法是规定死的,我们只能学习,不能更改人家规定
    	return 0;
    }
在这里插入图片描述
  • 提醒大家注意传值默认采用从左到右依次给予的方式进行赋值。

    • 很多人会对这种做法感到好奇。
    • 但需要注意的是我们在模仿他人的语法结构来构建我们的系统。
    • 可是如果我们不接受这种规范化的操作方式,
    • 完全可以选择开发属于自己的语言体系,
    • 比如探索X语言的可能性?
    1. 💦半缺省参数
    • 半缺省参数必须从右往左依次来给出,不能间隔 着给,看下面的例子
复制代码
    //半缺省
    void TestFunc(int a, int b = 10, int c = 20)  //必须从右往左连续缺省,不能间隔
    {
    	cout << "a = " << a << endl;
    	cout << "b = " << b << endl;
    	cout << "c = " << c << endl <<endl;
    }
    
    int main()
    {
    	//要传的放在前边,爱传不传的放在后边
    	TestFunc(1);//这第一个参数必须传
    	TestFunc(1, 2);
    	TestFunc(1, 2, 3);
    	//不能这样TestFun(,,1) 原因很简单,因为这不叫C++
    	return 0;
    }
在这里插入图片描述

3.💦 缺省参数不可以在函数声明和定义中共存 ,建议应放置于声明部分🔥 象一位lder brother(就像不知道是母亲在做决定还是父亲在主导家庭事务一样有趣)🔥

🍭举例:

复制代码
    #include<stdio.h>
    #include<stdlib.h>
    
    struct Stack
    {
    	int\* a;
    	int top;
    	int capacity;
    };
    
    //部分缺省
    void StackInit(struct Stack\* ps,int capacity = 4)
    {
    	ps->a = (int\*)malloc(sizeof(int)\*capacity);
    	ps->top =  0;
    	ps->capacity = capacity;
    }
    
    int main()
    {
    	struct Stack st;
    	StackInit(&st);//不知道栈最多存多少数据,就用缺省值初始化
    	StackInit(&st, 100);//知道我一定会插入100个数据,就可以显示传参数100,提前开好空间,插入数据避免扩容,这样可以减少增容次数,提高效率
    
    	return 0;
    }

🌍 5.函数重载

自然语言中,一个词可以有多种意义,人能够通过上下文来判断该词所指的具体意义,即这种现象被称为意义重叠.例如:过去有个笑话,国家里有两个体育项目大家几乎不用关注也不用担心.一个是乒乓球,另一个是男足.前者是"谁也赢不了!",后者也是"谁也赢不了!".

🌈5.1 函数重载概念

**函数重载:**是一种特殊的实现方式,在C++语言中允多多个具有相同名称但参数不同的函数在同一作用域内被定义。每个同名函数的具体参数设置(包括参数数量、类型以及类型顺序)各不相同。其主要应用在于解决实现相同或相似功能但针对不同类型数据的问题。

复制代码
    #include<iostream>
    using namespace std;
    
    // 1、参数类型不同
    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;
    }
    
    // 2、参数个数不同
    void f()
    {
    	cout << "f()" << endl;
    }
    void f(int a) 
    {
    	cout << "f(int a)" << endl;
    }
    
    // 3、参数类型顺序不同
    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()
    {
    	Add(10, 20);
    	Add(10.1, 20.2);
    	f();
    	f(10);
    	f(10, 'a');
    	f('a', 10);
    	return 0;
    }

结果如下:👇🏻

在这里插入图片描述

下面思考一下这两个函数支持冲载吗?👇🏻

复制代码
    short Add(short left, short right) 
    {
    	return left + right;
    }
    int Add(short left, short right) 
    {
    	return left + right;
    }

❌不能说函数重载与返回值不同的情况不存在❗ 实际上是由于参数的不同导致的

函数重载的意义就是让用的很方便,就像在用同一个函数一样

🌈5.2 C++支持函数重载的原理–名字修饰(name Mangling)和extern “C”

这部分要单独写一篇文章,8月中更新,不鸽👻

🌍 6.引用

🌈6.1 引用的概念

在C/C++语言中,对已存在的变量进行别名引用并不创建新的变量对象;这种操作不会为引用变量预留额外的内存空间;相反地,它实现了与原变量的共享使用同一个内存区域

比如:李逵,在家称为"铁牛",江湖上人称"黑旋风"。

在这里插入图片描述

类型& 引用变量名(对象名) = 引用实体

复制代码
    void TestRef()
    {
     	int a = 10;
     	int& ra = a;//<====定义引用类型
     
    	printf("%p\n", &a);
    printf("%p\n", &ra);
    }

通过监视窗口我们可以看到—— a和b的地址相同

在这里插入图片描述

所以我们知道原来引用只是对原来的空间起了个“花名”

注意:引用类型必须和引用实体是同种类型的

🌈6.2 引用特性
  1. 💦引用在定义时必须初始化
    好比🍭:你要给谁起别名,这个谁要先说戳来
在这里插入图片描述
  1. 💦 一个变量可以有多个引用
    好比🍭:一个人有多个外号
复制代码
    int main()
    {
    	// 一个变量可以有多个引用 —— 好比一个人可以有很多个外号一样
    	int a = 0;
    	int& b = a; //引用, 在类型和变量之间
    	int& c = a;
    	int& d = b;
    }
在这里插入图片描述
  1. 💦一旦对一个实体进行引用后,则不能再对其他实体进行引用。
    例如agger:在本质上是一个可靠的人,在建立联系后则永远不再改变。
    而像一个不忠的老丈人,在婚姻解约后依然故作忠诚。

思考👇🏻 b是x的别名呢? 还是x赋值给b呢?

复制代码
    int main()
    {
    	int a = 10;
    	int& b = a;
    
    	int x = 20;
    	b = x;
    	return 0;
    }
在这里插入图片描述

通过调试后看到,很明显是赋值了,地址都没改动

🌈6.3 常引用

我们知道,const修饰只读 ,引用修饰读和写

const引用🌏

  1. 权限扩大
复制代码
    	const int a = 10;//只读
    	int& b = a;//编译器报错 - 权限扩大 - int可读可写
  1. 权限缩小
复制代码
    	int c = 10;//可读可写
    	const int& d = c;//d是c的别名,缩小成只读 —— 权限缩小
  1. 权限平移
复制代码
    	const int a = 10;
    	const int& b = a;//权限不变

接下来再看看这个例子⚡

复制代码
    int main()
    {
    	int ii = 1;
    	double dd = ii;
    	//int& rdd = ii; //编译出错 
    	const double& rdd = ii;	//编译通过
    	return 0;
    }

在隐式类型转换过程中会产生临时变量,在这种情况下带有常属性的类型与const一致。由于不允许权限范围扩大,在引用时需附加const关键字。

在这里插入图片描述

简短回顾:const展现出强大的接收能力(const type &)——无条件接纳,能够接纳的对象类型极为丰富与广泛

✨const的权限放大和缩小只在指针和引用 奏效

鉴于此,在if函数中不修改参数n的情况下,默认传递参数的方式可能导致权限放大风险。因此,在这种情况下建议采用const&传参的方式进行操作。

复制代码
    	void fun2(const int& n)
🌈6.4 使用场景
💦1.做参数
复制代码
    void Swap(int& r1, int& r2)
    {	
    	int tmp = r1;	
    	r1 = r2;	
    	r2 = tmp;
    }
    int main()
    {
    	int x = 10;
    	int y = 20;
    //这里相当于把本身传了过去
    	Swap(x, y);//传引用
    
    	printf("a = %d,b = %d\n", x, y);
    	return 0;
    }

上述的调用方法就是在传引用 做输出型参数, r1,r2就是x,y的别名

这样不就是指针的用法吗?
我们举个例子🍭:

以SListPushBack函数为例,在实现过程中采用传递引用的方式进行改造。其中phead被定义为plist的别名,在这种设计下对phead进行修改相当于直接修改对应的plist对象。这种方式避免了像处理指针那样复杂的操作机制。

在这里插入图片描述
💦2.做返回值

传值返回:生成一个返回对象的copy作为函数调用的返回值

我们平时见到的最常见的就是传值返回
特点:返回值是在函数栈帧销毁之前进行一次拷贝操作并将其存放在临时变量中,因此,在Count中存储的是n的拷贝。

请添加图片描述

🔥如果是static的关键字被使用,则变量会被分配到静态区,并且所有栈帧都会位于堆区。然而普通的编译器处理起来会比较复杂,并且仍然会复制一份代码。

通过参照上述动画演示的结果来看, Count栈帧已经被成功销毁, 依然获取n返回值的结果, 那么将n初始化为随机值呢? 显然存在一个问题

  • 当n值较小时(如4或8个字节),通常情况下寄存器单元会被用来作为临时存储空间。
    • 在n较大时(如几百字节或更大),临时变量会被存储在主函数所在的栈区中。

传引用返回:返回n(返回对象)的别名

复制代码
    int& Count()
    {
    	int n = 0;
    	n++;
    	// ...
    	return n;
    }
    int main()
    {
    	int ret = Count();
    	return 0;
    }

传引用返回 ,return c; 即是返回c的引用,ret就是c的别名(引用)。

你是否能察觉这段代码存在潜在的问题?因为引用返回的方式并未生成c的拷贝——为了减少对[大对象 + 深拷贝对象]进行复制从而提高性能——而是直接将c的对象作为ret变量的一个别名副本提供给调用者。然而,在这种情况下Add函数栈帧已销毁——因此当程序试图回溯至c的空间时就会产生非法访问错误。

但我们发现还是能正常打印,越界就一定报错吗,犯罪一定会被抓吗?

在这种情况下,在未覆盖c空间的情况下,ret可能借由某种途径获取看似正确的数据;而当清理了该空间时,则会接收到不确定的数据。

在这里插入图片描述

所以我们总结出一个结论❗:

  • 🥗 如果函数的返回值越出了作用域,则:
    • 如果返回对象没有被还给系统(全局变量),则可以直接引用该对象进行操作;
    • 如果已经将该对象还给系统了(局部变量),则必须采用传值方式进行操作,并避免直接引用局部变量的引用(因为这可能得到随机的中间结果)。

在日常场景中,传引用返回通常较少使用,在类和对象系统中具有重要应用价值。后续内容将逐步展开讨论相关内容。

为此我们还可以把 n 置为全局变量 :+static

复制代码
    int& Count()
    {
    	static int n = 0;//static
    	n++;
    	// ...
    	return n;
    }
    int main()
    {
    	int ret = Count();
    	cout << ret << endl;
    	return 0;
    }

🍤例:我们改一个函数加深一下对传引用返回的好处

复制代码
    int& SLAt(SL& s, int pos)
    {
    	assert(pos >= 0 && <= s.size);
    
    	return s.a[pos];
    }

执行这个函数后,在后续操作中发现空间未被释放。由于sl是由malloc产生的 ,因此位于区域而不会被系统回收。

在这里插入图片描述

🍂总结:

  1. 🍳前提:超出作用域后不再受限制。
  2. 使用场景:
    1️⃣ 作为参数使用——采用输出型参数类型(如...),适用于大规模对象传递。
    2️⃣ 作为返回值——采用输出型返回对象类型(如...),允许调用者直接修改其内容以提高效率。
🌈6.5 传值、传引用效率比较

使用变量作为参数或返回值类型时,在传入和返回的过程中(即传参和返参阶段),程序不会直接传递实参或将变量本身立即返还给调用方。相反地,则会采用一种间接的方式进行操作:即要么传递实参(即生成一个与之完全相同的副本),要么生成一个与原变量内容相同的临时副本,并因此导致效率低下。特别地,在参数或返回类型非常庞大的情况下(即当涉及的数据规模较大时),这种做法所带来的效率降低更加明显。通过引用机制,则能显著提升能效水平。

💦话不多说下面我们来测试一下:

复制代码
    #include <time.h>
    //全局变量
    struct A { int a[10000]; };
    
    void TestFunc1(A a) {} //传值 ~ 生成拷贝
    
    void TestFunc2(A& a) {}//引用别名
    
    void TestRefAndValue()
    {
    	A a;
    	// 以值作为函数参数
    	size\_t begin1 = clock();
    	for (size\_t i = 0; i < 100000; ++i)
    		TestFunc1(a);
    	size\_t end1 = clock();
    	// 以引用作为函数参数
    	size\_t begin2 = clock();
    	for (size\_t i = 0; i < 100000; ++i)
    		TestFunc2(a);
    	size\_t end2 = clock();
    	// 分别计算两个函数运行结束后的时间
    	cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;
    	cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;
    }

调用10000次的结果⚡

在这里插入图片描述

引用做参数如此,做返回值就不用我多说了吧

🌈6.6 引用和指针的区别

以下的建议不要背,要去理解,理解透了看一眼就好⚡

  1. 在引用概念上将一个变量命名为另一个变量(即定义一个变量的别名),同时该变量存储的是目标变量的内存地址。
  2. 在定义指针时必须进行初始化操作;而如果使用的是常量或静态变量,则不需要显式地对它们进行初始化。
  3. 一旦对实体进行引用操作后,则不能再对其他实体进行引用。
  4. 没有NULL类型的引用(即不允许出现无意义的无目标值),但存在带有NULL值的指针(即某些情况下指向空对象)。
  5. 在使用sizeof运算符获取对象大小时的结果与用指针获取地址所占字节结果不同:前者给出的是对象的实际大小信息;后者始终给出的是地址空间所占字节数目(4字节/8字节)。
  6. 引用自加操作会导致目标类型增加1;而指针自加操作则会使得指针向后偏移其所在类型的大小。
  7. 多级指针是允许存在的;不存在多级间接引用的情况。
  8. 访问对象的方式不同会导致显式解引用的需求出现:当通过常量或静态变量访问对象时,默认会解引用;而当通过函数或构造函数等间接方式访问对象时,则需要手动解引用。
  9. 相比而言,在使用引的时候会更加安全一些:因为隐式的内存管理由编译器负责处理;而如果直接使用未被初始化的内存区域可能会导致不可预测的行为发生。

底层实现上 其实是有空间的,并非完全没有余地可以发挥,在引用机制中采用的是指针复制的方式

我们来看下引用和指针的汇编代码对比:

在这里插入图片描述

发现是引用和指针在底层实现是一样的,但语法上不一样

在这里插入图片描述

相比之前所学的内容来说,提升幅度非常显著!比如说是来自同一条流水线生产的鞋子。价格差异较大吗?不光是一条流水线生产的产品存在价格差异哦——有的卖上 thousand 块钱一件有的却仅需 hundred 块钱就能买到还从解剖学角度来看竟然出自同一个生产厂家!这种对比真是让人忍俊不禁呢 这种对比使得理解变得更加直观了哦

🌍 7.内联函数

为了提高程序效率,在1到10行之间的简短功能模块频繁调用会产生持续占用堆栈帧资源的问题

深入分析表明,C++在一定程度上是对C语言的一种改进和完善,并发展出了内联函数(inline)技术

接下来我们先回顾一下宏:

复制代码
    #define ADD(a,b) ((a)+(b))//要注意每一个括号的含义
    
    int main()
    {
    	cout << ADD(1, 2) << endl;
    	return 0;
    }
    //括号用的场景
    // ADD(1, 2) \* 3;// ((1)+(2))\*3 外面的括号
    // ADD(x | y, x & y);// ((x | y)+(x & y)) 里面的括号————运算符的优先级

🎶优点 :增强代码的复用性、 提高性能。
🎶缺点

  1. 由于代码可读性和可维护性受到影响。
  2. 检查表明该方法难以调试宏。
    (这是因为预编译阶段进行了变量替换)
  3. 缺乏严格的类型安全检查。

那么我请来了宏的大哥

在这里插入图片描述
🌈7.1 概念

以通过关键字inline进行修饰的函数被称为内联函数,在编译过程中C++编译器会在调用该内联函数时将其展开。避免了因函数调用而产生的栈帧创建开销,并且有效减少了程序运行过程中的相关开销。

在这里插入图片描述

如果在上述函数前添加inline关键字将其改为内联形式,在编译期间编译器会将被调用的函数替换成其体

在调试模式下必须对编译器进行配置才能使代码被展开。因为在调试模式中,默认情况下编译器不进行优化操作。请参考以下详细配置方法以完成设置。

在这里插入图片描述

可以看见内联函数,没有调用而是直接展开

在这里插入图片描述
🌈7.2 内联函数特性

在编程中,inline技术通过将函数直接嵌入调用处(即在执行时直接展开),从而实现了空间与时间的权衡。当编译器识别到可以采用内联方式优化的函数时,在编译阶段会将这些函数直接展开为代码(即替换掉原函数调用),从而减少后续运行时的开销。潜在的缺点在于这样做可能会导致目标文件体积增大;尽管如此,在多数情况下这种方法能有效减少运行时开销并提升程序的整体执行效率

在这里插入图片描述
  1. 从编译器的角度来看仅作为一个参考建议 ,各编译器对inline实现机制可能存在差异。通常建议将函数定义规模较小(具体由各个编译器内部实现)。若函数被指定为inline且内部包含循环或递归等结构,则在优化过程中会避免内联。
在这里插入图片描述
  1. 立即风格声明和定义不应分开展开(inline),因为这会导致链接错误(link error)。由于inline元素被展开后将不再具有对应的函数地址(function address),因此无法形成正确的链接(link)。通常建议在定义中包含内联内容(inline)。
复制代码
    // F.h
    #include <iostream>
    using namespace std;
    inline void f(int i);
    // F.cpp
    #include "F.h"
    void f(int i) 
    {
    	cout << i << endl;
    }
    // main.cpp
    #include "F.h"
    int main()
    {
    	f(10);
    	return 0;
    }
    // 链接错误:main.obj : error LNK2019: 无法解析的外部符号 "void \_\_cdecl f(int)" (?f@@YAXH@Z),该符号在函数 \_main 中被引用

🌍8. auto关键字(C++11)

🌈8.1 类型别名思考
🌈8.2 auto简介

在早期开发C/C++语言的过程中, 其用途体现在' auto '关键字上. 通过关键字' auto '修饰的变量能够自动生成内存块, 在内存管理方面展现出显著的优势. 然而令人惋惜的是, 在过去很长一段时间内没有人充分利用这一特性. 我们可以进一步探索其应用潜力.

在C++11中标准委员会推出了 auto 这一新特性其本质是: auto不再是用于声明存储类型的工具而是被用作类型推断机制指导编译器自动选择变量的数据类型。

可以自动推导类型💥

在这里插入图片描述

在C++编程中使用auto关键字定义变量时必须在声明时就对其进行初始化操作;当编译器在构建程序时会分析初始值并动态确定其具体类型。这种特性意味着auto并不是一种传统的数据类型声明(如int或char),而是起到了一种占位符的作用:只有等到实际赋值初始值后(例如赋值为int 5),编译器才会明确该变量的实际存储类型(如int)。因此,在这种情况下auto更多地体现了语言机制上的灵活性而非静态类型的约束

🌈8.3 auto的使用细则

当使用auto关键字声明指针变量时,在不指定具体类型的情况下,默认会生成指向该数据类型的地址型指针(即带有*'号的动态内存地址)。然而,在这种情况下与使用纯自动态内存地址(如std::unique_ptr)之间并无实质区别。但如果要声明引用类型的变量,则需在声明前添加&符号以确保引用的有效性

复制代码
    int main()
    {
    	int x = 10;
    	auto a = &x;  //int\*
    	auto\* b = &x; //int\* 强调一定要传指针
    	auto& c = x;  //int 强调c是一个引用 c是x的别名
    
    	cout << typeid(a).name() << endl;
    	cout << typeid(b).name() << endl;
    	cout << typeid(c).name() << endl;
    	\*a = 20;
    	\*b = 30;
    	c = 40;
    	return 0;
    }
在这里插入图片描述

当在同一行为多个变量赋值时,在声明这些变量时必须确保它们具有相同的数据显示类型;如果这些变量不是同一数据类型的,则编译器会报错。这是因为现代编程语言仅根据第一个数据类型的推导来确定其余变量的数据类型。

复制代码
    void TestAuto()
    {
     	auto a = 1, b = 2; 
     	auto c = 3, d = 4.0; // 该行代码会编译失败,因为c和d的初始化表达式类型不同
    }
🌈8.4 auto不能推导的场景

此代码在编译时出现错误:此处代码尝试将auto声明为函数的形参类型(即参数),但因缺少足够的上下文信息而无法确定该变量的具体类型信息。由于C++的静态语义特性,在这种情况下无法推断变量a的具体类型。

复制代码
    void TestAuto(auto a)
    {}
  1. auto不能直接用来声明数组
在这里插入图片描述

在实际应用中(auto),其主要应用场景包括与后续章节将介绍的C++11新特性for循环协同工作以及与lambda表达式协同工作。

🌍9. 基于范围的for循环(C++11)

🌈9.1 范围for的语法

在C++98中如果要遍历一个数组,可以按照以下方式进行:

复制代码
    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;
    	return 0;
![img]()
![img]()
![img]()
    
    **既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!** **由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新** **[需要这份系统化资料的朋友,可以戳这里获取]()**
    
    
    #### 🌈8.4 auto不能推导的场景
    
    
    1. auto不能作为函数的参数  
     此处代码编译失败,**auto不能作为形参类型**,因为编译器无法对a的实际类型进行推导

void TestAuto(auto a)
{}

复制代码
 auto不能直接用来声明数组
![在这里插入图片描述]()
    
    
    auto在实际中最常见的优势用法就是跟以后会讲到的C++11提供的新式for循环,还有lambda表达式等  
     进行配合使用。
    
    
    ### 🌍9. 基于范围的for循环(C++11)
    
    
    #### 🌈9.1 范围for的语法
    
    
    在C++98中如果要遍历一个数组,可以按照以下方式进行:

该函数实现了以下功能:初始化一个包含五个连续整数的一维数组,并按顺序打印出每个元素的值。具体实现步骤如下:首先定义变量arr为一个整型指针类型;随后将变量arr初始化为包含五个连续整数的一维数组;接着使用for循环结构遍历数组中的每一个元素;在循环体内使用标准输出语句依次打印每个元素的值,并附加一个空格;最后调用标准输出语句打印换行以显示结果。

该图片暂未成功加载中。
此图文件未能正确解析。
当前该资源链接无法访问。

针对初学者设计的基础学习材料与为资深数据工作者提供的高级学习资源相结合,《课程》系统性地构建起完整的知识体系并覆盖了数据科学领域的95%以上核心知识点

因文件数量较多,仅作为参考提供,完整包含 canonical面试题库,学习资料,代码解析文档,实践案例库,课程规划路线图,教学视频资源库,后续将持续更新丰富内容

因文件数量较多,仅作为参考提供,完整包含 canonical面试题库,学习资料,代码解析文档,实践案例库,课程规划路线图,教学视频资源库,后续将持续更新丰富内容

需要这份系统化资料的朋友,可以戳这里获取

全部评论 (0)

还没有任何评论哟~