【C++】:函数重载,引用,内联函数,auto关键字,基于范围的for循环,nullptr关键字

news2024/11/17 21:22:25

目录

  • 一,函数重载
    • 1.1 函数重载的定义
      • 1.1.1.形参的类型不同
      • 1.1.2参数的个数不同
      • 1.1.3.参数的顺序不同
      • 1.1.4.有一个是缺省参数构成重载。但是调用时存在歧义
      • 1.1.5.返回值不同,不构成重载。因为返回值可接收,可不接受,调用函数产生歧义。
    • 1.2 C++支持函数重载的原理 -- 名字修饰
  • 二,引用
    • 2.1 引用的概念
    • 2.2 引用的使用场景
      • 2.2.1 引用做参数
      • 2.2.2 引用做返回值
    • 2.3 引用特性
    • 2.4 引用的权限问题
      • 2.4.1 举例1
      • 2.4.2 举例2
      • 2.4.3 举例3
      • 2.4.4 总结
    • 2.5 常引用
      • 2.5.1 类型转换时
      • 2.5.2 表达式运算时
    • 2.6 传值、传引用效率比较
    • 2.7 引用和指针的区别
  • 三,内联函数
    • 3.1 内联函数的概念
    • 3.2 inline 关键字
    • 3.3 内联的特性
  • 四,auto关键字(C++11)
    • 4.1 给类型取别名
    • 4.2 可由初始化自动推导类型
    • 4.3 auto不能推导的场景
  • 五,基于范围的for循环
    • 5.1 范围for的语法
    • 5.2 范围for的使用条件
  • 六,nullptr关键字

一,函数重载

在C语言中,同名函数是不能出现在同一作用域的,但是在C++中却可以,但是要满足函数重载的规则。

那什么是函数重载呢?它的规则是什么呢?

1.1 函数重载的定义

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

举几个例子:

1.1.1.形参的类型不同

void Swap(int* pa, int* pb)
{
	cout << "void Swap(int* pa, int* pb)" << endl;
}

void Swap(double* pa, double* pb)
{
	cout << "void Swap(double* pa, double* pb)" << endl;
}

int main()
{
	int a = 0, b = 1;
	double c = 1.1, d = 2.2;

	Swap(&a, &b);
	Swap(&c, &d);

	return 0;
}

在这里插入图片描述

1.1.2参数的个数不同

在这里插入图片描述

1.1.3.参数的顺序不同

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

void f(char c, int d)
{
	cout << "void f(char c, int d)" << endl;
}

int main()
{
	int a = 0, b = 1;
	double c = 1.1, d = 2.2;

	f(1,'c');
	f('d',3);

	return 0;
}

在这里插入图片描述

1.1.4.有一个是缺省参数构成重载。但是调用时存在歧义

void f()
{
	cout << "void f()" << endl;
}

void f(int a = 10)
{
	cout << "void f(int a = 10)" << endl;
}


int main()
{
	int a = 0, b = 1;
	double c = 1.1, d = 2.2;

	f();
	f(5);


	return 0;
}

在这里插入图片描述

1.1.5.返回值不同,不构成重载。因为返回值可接收,可不接受,调用函数产生歧义。

int f()
{
	return 0;
}

void f()
{
	cout << "void f(char c, int d)" << endl;
}

int main()
{
	int a = 0, b = 1;
	double c = 1.1, d = 2.2;

	int ret = f();
	cout << ret << endl;
	f();

	return 0;
}

在这里插入图片描述

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

为什么C++存在重载,C语言不支持?C++为什么支持?

这两个问题深究起来十分复杂。它们与预处理、编译、汇编、链接有极大的关系,这里只是大致解释,只要记住结论即可。

在一般的工程项目中,都会进行多文件操作,那一个函数就一定会声明与定义分离。

![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/233f4fee513464e831df277ce671d5e.png

通过上图我们需要知道的两点:

1.函数的地址:转到反汇编时,每个函数都有一堆要执行的指令,函数的地址是第一句指令的地址。
2.函数的地址要依靠函数的定义生成,而不是函数声明。

函数的重载发生在函数链接的时候。
C语言在链接时,直接用函数名去查找,当遇到同名函数时,无法区分,就不支持重载。
C++在链接时,直接用修饰后的函数名去查找,当遇到同名函数时,可以区分,支持重载。

其实不同的编译器有不同的函数名修饰规则。
在Linux的g++编译器下:

C语言不支持重载,直接就是函数名:
在这里插入图片描述

C++支持重载,有函数名的修饰:

在这里插入图片描述

上面的图文看不懂没关系。通过上面的分析。可以得出结论:

  • 在项目工程中,使用多文件操作,函数的定义与声明分离,而在链接的时候,要用函数名去找地址。C语言直接用函数名去查找,当遇到同名函数时,无法区分,而C++有函数名修饰规则,只要参数不同,修饰出来的名字就不一样,可以区分 。并且不同编译器的修饰规则不同。

二,引用

2.1 引用的概念

引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间也可以给别名再取别名。

举个例子:

int main()
{
	int a = 1;

	//引用:&  b是a的别名
	int& b = a;

	//也可以给别名取别名
	int& c = b;

	//值相同,地址也相同
	cout << "a = " << a<< endl; 
	cout << "b = " << b << endl;
	cout << "c = " << c << endl << endl;

	cout << "&a = " << &a << endl;
	cout << "&b = " << &b << endl;
	cout << "&c = " << &c << endl;


	return 0;
}

在这里插入图片描述

2.2 引用的使用场景

2.2.1 引用做参数

最典型的例子就是我们经常使用的交换函数


//a是x的别名,b是y的别名。a,b的交换就是x,y的交换
void Swap(int& a, int& b)
{
	int tmp = a;
	a = b; 
	b = tmp;
}

int main()
{
	int x = 1;
	int y = 2;

	Swap(x, y);//这里就不用传地址过去了

	cout << x << ":" << y << endl;

	return 0;
}

2.2.2 引用做返回值

这里暂时不解释,到后面学习了类和对象后再解释,会更加清晰。

2.3 引用特性

1.引用在定义时必须初始化
2.一个变量可以有多个引用
3.引用一旦引用一个实体,再不能引用其他实体

第1,2条容易理解,这里说明第三条:

int main()
{
	int x = 0;
	int& y = x;//y是x的别名

	int z = 1;

	//这里y是z的别名,还是z赋值给y?
	//是赋值。引用一旦引用一个实体,就不能再改变指向了!
	y = z;

	cout << "x = " << x << endl;
	cout << "y = " << y << endl;
	cout << "z = " << z << endl << endl;

	return 0;
}

在这里插入图片描述

2.4 引用的权限问题

这里所说的权限有:权限放大,权限缩小,权限平移

2.4.1 举例1

int main()
{
	//这里权限放大了。m是只读,n变成m的别名后,可读可写。
	const int m = 0;
	
	//int& n = m; //err
	
	int p = m;//可以,不是权限的放大。
              //只是把m拷贝给p,p的修改不影响m。

    //n也是只读的,权限的平移
    const int& n = m;//可以
    
	return 0;
}

2.4.2 举例2

int main()
{
	const int m = 0;

	// 权限的放大
	//p1可以修改,*p1不行,const修饰的是p1指向的内容,即*p1。
	const int* p1 = &m;
	p1++;//可以

	//int* p2 = p1;//err. *p2是可以修改的,所以权限放大了。
		
	return 0;
}

2.4.3 举例3

int main()
{
	//权限的缩小
	int x = 0; 
	int& y = x;

	const int& z = x;//可以

	y++;//x,z都会修改

	return 0;
}

2.4.4 总结

1.权限放大问题存在于引用和指针里,普通的赋值拷贝不会
2.权限只能缩小,平移,不能放大

2.5 常引用

2.5.1 类型转换时

因为类型转换的过程中会生成临时变量,这个临时变量具有常性(相当于被const修饰)。权限被放大了。

int main()
{
	double d = 3.24;

	//类型转换
	int i = d;

	//int& r = d;err 
	
	const int& r = d;//可以。加了const就相当于权限平移了。

	return 0;
}

2.5.2 表达式运算时

表达式运算也会生成临时变量,解释同上。

int main()
{	
	int x = 0, y = 1;

	//表达式运算也会生成临时变量
	//int& r2 = x + y; //err

	const int& r2 = x + y; //可以

	return 0;
}

2.6 传值、传引用效率比较

其实这与函数的传值,传址调用类似。当函数传值调用时,会在内存中又开辟空间临时拷贝,当参数较大时,效率低下。而传址调用却不会,会提高效率。

#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 < 10000; ++i)
		TestFunc1(a);
	size_t end1 = clock();
	// 以引用作为函数参数
	size_t begin2 = clock();
	for (size_t i = 0; i < 10000; ++i)
		TestFunc2(a);
	size_t end2 = clock();

	// 分别计算两个函数运行结束后的时间
	cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;
	cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;
}

int main()
{
	TestRefAndValue();

	return 0;
}

在这里插入图片描述

注意:0毫米表示运行时间小于1毫米。

2.7 引用和指针的区别

语法概念上引用就是一个别名,没有独立空间,和其引用实体共用同一块空间。

int main()
{
		int a = 10;
		int& ra = a;

		cout << "&a =  " <<  &a << endl;
		cout << "&ra = " << &ra << endl;
	
	return 0;
}

在这里插入图片描述

底层实现上实际是有空间的,因为引用是按照指针方式来实现的。

int main()
{
 int a = 10;
 
 int& ra = a;
 ra = 20;
 
 int* pa = &a;
 *pa = 20;
 
 return 0;
}

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

在这里插入图片描述

引用和指针的不同点:

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

三,内联函数

如果有一个频繁调用的小函数,例如Swap交换函数,在频繁调用时会有建立栈帧的消耗,我们想消除这样的消耗,该怎么做呢?

C语言中是使用宏函数解决,C++中就可以使用内联函数。

3.1 内联函数的概念

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

3.2 inline 关键字

在没有加 inline 之前:

 int Add(int x, int y)
{
	return x + y;
}

int main()
{
	int c = Add(1, 2);
	cout << c << endl;

	return 0;
}

![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/a2e02365da664bc89959a7e1cc548147.png

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

inline int Add(int x, int y)
{
	return x + y;
}

int main()
{
	int c = Add(1, 2);
	cout << c << endl;

	return 0;
}

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

在这里插入图片描述

转到汇编中:

在这里插入图片描述

3.3 内联的特性

1.inline是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会用函数体替换函数调用,缺陷:可能会使目标文件变大,优势:少了调用开销,提高程序运行效率。

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

在这里插入图片描述

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

四,auto关键字(C++11)

其实 auto 关键字的介绍和使用内容十分丰富,我们现在这个阶段不需要了解太详细,在以后的学习中会边学边了解。

4.1 给类型取别名

随着程序越来越复杂,程序中用到的类型也越来越复杂,经常体现在:类型难于拼写,含义不明确导致容易出错

有人会想到 typedef 不也可以给类型取别名吗?但是在某些场合下是有缺陷的:

typedef char* pstring;

int main()
{
	//const pstring p1;//err. const修饰指针p1本身,
	                   //而const修饰的指针要初始化
	                           
	const pstring* p2;  // 可以. const修饰 *p2

	return 0;
}

4.2 可由初始化自动推导类型

比如,下面的写法是正确的:

int main()
{
	int i = 0;
	
	//根据右边得到初始化自动推导类型
	auto j = 7;

	return 0;
}

注意:下面的 typeid(变量名).name 判断一个对象的类型

int TestAuto()
{
	return 10;
}

int main()
{
	int a = 10;
	auto b = a;
	auto c = 'a';
	auto d = TestAuto();

	//
	cout << typeid(b).name() << endl;
	cout << typeid(c).name() << endl;
	cout << typeid(d).name() << endl;

	//auto e; 无法通过编译,使用auto定义变量时必须对其进行初始化
	return 0;
}

在这里插入图片描述

  • 使用auto定义变量时必须对其进行初始化在编译阶段编译器需要根据初始化表达式来推导auto的实际类型。因此auto并非是一种“类型”的声明,而是一个类型声明时的“占位符”,编译器在编译期会将auto替换为变量实际的类型。

4.3 auto不能推导的场景

1.auto不能作为函数的参数
2.auto不能直接用来声明数组

五,基于范围的for循环

5.1 范围for的语法

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

void TestFor()
{
 int array[] = { 1, 2, 3, 4, 5 };
 for (int i = 0; i < sizeof(array) / sizeof(array[0]); ++i)
     array[i] *= 2;
 
 for (int* p = array; p < array + sizeof(array)/ sizeof(array[0]); ++p)
     cout << *p << endl;
}

对于一个有范围的集合而言,由程序员来说明循环的范围是多余的,有时候还会容易犯错误。因此C++11中引入了基于范围的for循环。for循环后的括号由冒号“ :”分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围

void TestFor()
{
 int array[] = { 1, 2, 3, 4, 5 };
  
  //注意:这里如果要改变原数组元素的值,要加引用&
 for(auto& e : array)
     e *= 2;
 
 for(auto e : array)
     cout << e << " ";
 
 return 0;
}

注意:与普通循环类似,可以用continue来结束本次循环,也可以用break来跳出整个循环。

5.2 范围for的使用条件

1.for循环迭代的范围必须是确定的。
2.迭代的对象要实现++和==的操作。(关于迭代器这个问题,以后会讲,现在提一下,没办法讲清楚,现在大家了解一下就可以了)

六,nullptr关键字

在良好的C/C++编程习惯中,声明一个变量时最好给该变量一个合适的初始值,否则可能会出现不可预料的错误,比如未初始化的指针。

在C语言中,如果一个指针没有合法的指向,我们基本都是按照如下方式对其进行初始化:

void TestPtr()
{
 int* p1 = NULL;
 int* p2 = 0;
 
 // ……
}

NULL实际是一个宏,在传统的C头文件(stddef.h)中,可以看到如下代码:

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

可以看到,NULL可能被定义为字面常量0,或者被定义为无类型指针(void)的常量* 。不论采取何种定义,在使用空值的指针时,都不可避免的会遇到一些麻烦,比如:

![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/fe6bbcdae8264ae2b7b7771de6e53add.png

程序本意是想通过f(NULL)调用指针版本的f(int*)函数,但是由于NULL被定义成0,所以会调用f(int)函数,因此与程序的初衷相悖。

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

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1610717.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何设计单元测试用例?

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 最近一些大公司在进行去测试化的操作&#xff0c;这一切的根源大概可以从几年前微软一刀切砍掉所…

【深度学习实战(10)】图像推理之预处理

一、预处理流程 在把一张图像送入模型进行推理时&#xff0c;需要先进行预处理&#xff0c;预处理流程包括&#xff1a; &#xff08;1&#xff09;读取图像 &#xff08;2&#xff09;尺寸调整&#xff0c;letter_box&#xff08;不失真&#xff09; &#xff08;3&#xff0…

MATLAB绘制圆锥曲线:抛物线,双曲线,椭圆

MATLAB绘制圆锥曲线:抛物线,双曲线,椭圆 clc;close all;clear all;warning off;%清除变量x linspace(-10, 10, 1000); % 创建一个x值的向量&#xff0c;范围从-10到10&#xff0c;共1000个点 y x.^2; % 计算每个x值对应的y值% 使用plot函数绘制图形 figure; % 创建一个新的图…

排序 “壹” 之插入排序

目录 ​编辑 一、排序的概念 1、排序&#xff1a; 2、稳定性&#xff1a; 3、内部排序&#xff1a; 4、外部排序&#xff1a; 二、排序的运用 三、插入排序算法实现 3.1 基本思想 3.2 直接插入排序 3.2.1 排序过程&#xff1a; 3.2.2 代码示例&#xff1a; 3.2.3…

使用Spring进行文件的上传和下载

概览 使用Spring进行文件的上传和下载Spring上传文件接口设计dubbo接口设计上传文件流的RPC的接口设计 Spring文件下载接口设计dubbo接口设计下载文件流的RPC的接口设计 spring上传文件大小控制 使用Spring进行文件的上传和下载 本文主要介绍在Spring框架下面调用微服务的dubb…

YOLOv9改进策略 | 添加注意力篇 | 利用ILSVRC冠军得主SENetV1改善网络模型特征提取能力

一、本文介绍 本文给大家带来的改进机制是SENet&#xff08;Squeeze-and-Excitation Networks&#xff09;其是一种通过调整卷积网络中的通道关系来提升性能的网络结构。SENet并不是一个独立的网络模型&#xff0c;而是一个可以和现有的任何一个模型相结合的模块(可以看作是一…

项目实践:贪吃蛇

引言 贪吃蛇作为一项经典的游戏&#xff0c;想必大家应该玩过。贪吃蛇所涉及的知识也不是很难&#xff0c;涉及到一些C语言函数、枚举、结构体、动态内存管理、预处理指令、链表、Win32 API等。这里我会介绍贪吃蛇的一些思路。以及源代码也会给大家放到文章末尾。 我们最终的…

【Ne4j图数据库入门笔记1】图形数据建模初识

1.1 图形建模指南 图形数据建模是用户将任意域描述为节点的连接图以及与属性和标签关系的过程。Neo4j 图数据模型旨在以 Cypher 查询的形式回答问题&#xff0c;并通过组织图数据库的数据结构来解决业务和技术问题。 1.1.1 图形数据模型介绍 图形数据模型通常被称为对白板友…

【Gradle如何安装配置及使用的教程】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

双链表的实现

我们知道链表其实有很多种&#xff0c;什么带头&#xff0c;什么双向啊&#xff0c;我们今天来介绍双向带头循环链表&#xff0c;了解了这个其他种类的链表就很简单了。冲冲冲&#xff01;&#xff01;&#xff01; 链表的简单分类 链表有很多种&#xff0c;什么带头循环链表&…

tcp-learner 数据包分析 20240420

输入输出&#xff1a; 数据包分析&#xff1a; learner和Adapter建立连接。 Learner让Adapter发送RST Adapter没有从SUT抓到任何回复&#xff0c;于是向learner发送timeout learner给adapter发送reset命令&#xff0c;让SUT重置。 这是第一次初始化&#xff0c;由于Adapter和…

Spring Boot后端与Vue前端融合:构建高效旅游管理系统

作者介绍&#xff1a;✌️大厂全栈码农|毕设实战开发&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。 &#x1f345;获取源码联系方式请查看文末&#x1f345; 推荐订阅精彩专栏 &#x1f447;&#x1f3fb; 避免错过下次更新 Springboot项目精选实战案例 更多项目…

【简单讲解下npm常用命令】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

【hackmyVM】whitedoor靶机

文章目录 信息收集1.IP地址2.端口探测nmapftp服务 3.访问主页 漏洞利用1.反弹shell2.尝试提权3.base64解密 提权1.切换用户2.john爆破3.切换Gonzalo用户4.vim提权 信息收集 1.IP地址 ┌─[✗]─[userparrot]─[~] └──╼ $fping -ag 192.168.9.0/24 2> /dev/null192.168…

ZYNQ NVME高速存储之EXT4文件系统

前面文章分析了高速存储的各种方案&#xff0c;目前主流的三种存储方案是&#xff0c;pcie switch高速存储方案&#xff0c;zynq高速存储方案&#xff0c;fpga高速存储方案。虽然三种高速存储方案都可以实现高速存储&#xff0c;但是fpga高速存储方案是最烂的&#xff0c;fpga…

Android Studio 新建Android13 代码提示Build Tools revision XX is corrupted无法编译解决

Android Studio 新建Android13 代码提示Build Tools revision XX is corrupted无法编译解决 文章目录 Android Studio 新建Android13 代码提示Build Tools revision XX is corrupted无法编译解决一、前言二、分析解决1、原因分析2、解决方法 三、其他1、Android13 新项目无法编…

什么是时间序列分析

时间序列分析是现代计量经济学的重要内容&#xff0c;广泛应用于经济、商业、社会问题研究中&#xff0c;在指标预测中具有重要地位&#xff0c;是研究统计指标动态特征和周期特征及相关关系的重要方法。 一、基本概念 经济社会现象随着时间的推移留下运行轨迹&#xff0c;按…

随身WiFi真实测评推荐!格行vs新讯随身wifi对比,公认最好的随身WiFi格行随身wifi有什么优势?

在当前移动网络高度发达的时代&#xff0c;随身 WiFi 已成为人们出差、旅行等场景中不可或缺的工具。格行和新讯是目前比较受欢迎的无线随身wifi。本次评测将对比分析这两款产品的区别&#xff0c;做为随身WiFi推荐第一名的格行随身wifi到底有什么优势呢&#xff1f; 品牌对比&…

[阅读笔记15][Orca]Progressive Learning from Complex Explanation Traces of GPT-4

接下来是微软的Orca这篇论文&#xff0c;23年6月挂到了arxiv上。 目前利用大模型输出来训练小模型的研究都是在模仿&#xff0c;它们倾向于学习大模型的风格而不是它们的推理过程&#xff0c;这导致这些小模型的质量不高。Orca是一个有13B参数的小模型&#xff0c;它可以学习到…

C++ 内存分区管理

一、栈区&#xff08;Stack&#xff09; 栈区用来存储函数的参数值、局部变量的值等数据。栈区是自动分配和释放的&#xff0c;函数执行时会在栈区分配空间&#xff0c;函数执行结束时会自动释放这些空间。栈区的数据是连续分配的&#xff0c;由系统自动管理。 注意事项&…