C++函数参数传递

目录

传值参数

指针形参

传引用参数

使用引用避免拷贝

使用引用形参返回额外信息

const形参和实参

指针或引用形参与const

数组形参

管理指针形参

使用标记指定数组长度

使用标准库规范

显式传递一个表示数组大小的形参

数组形参和const

数组引用形参

传递多维数组

含有可变形参的函数

initializer_list形参

传参

含有initializer_list形参的函数也可以同时拥有其他形参。

省略符形参


每次调用函数时都会重新创建它的形参,并用传入的实参对形参进行初始化。这个形参初始化的机理与变量初始化一样。

和其他变量一样,形参的类型决定了形参和实参交互的方式。如果形参是引用类型,它将绑定到对应的实参上;否则,将实参的值拷贝后赋给形参。

  • 当形参是引用类型时,我们说它对应的实参被引用传递或者函数被传引用调用。和其他引用一样,引用形参也是它绑定的对象的别名;也就是说,引用形参是它对应的实参的别名。
  • 当实参的值被拷贝给形参时,形参和实参是两个相互独立的对象。我们说这样的实参被值传递或者函数被传值调用。

传值参数

当初始化一个非引用类型的变量时,初始值被拷贝给变量。

此时,对变量的改动不会影响初始值:

int n=0;// int 类型的初始变量
int  i=n; //i是n的值的副本
i=42: // i的值改变;n的值不变
cout<<n<<endl;

传值参数的机理和上面这个完全一样,函数对形参做的所有操作都不会影响实参
也就是说,下面这个函数调用和上面这个是完全一样的

void A(int i)
{
i=42;
}int main()
{
int n=0;
A(n);
cout<<n<<endl;
}

指针形参

指针的行为和其他非引用类型一样。当执行指针拷贝操作时,接获的是指针的值,拷贝之后,两个指针是不同的指针。因为指针使我们可以间接地访问它所指的对象,所以通过指针可以修改它所指对象的值:

int n=0, i=42;
int *p = &n, *q= &i //p指向n;q指向i
*p=42; // n的值改变;p不变
p=q; // p现在指向了i;但是i和n的值都不变


指针形参的行为与之类似:

#include<iostream>
using namespace std;//该函数接受一个指针,然后将指针所指的值置为0void reset(int* ip)
{*ip = 0;// 改变指针ip所指对象的值ip = 0; //只改变了ip的局部拷贝,实参未被改变
}int main()
{int i = 42;cout << "调用之前:\n" << "i="<<i << endl <<"i的地址是"<< & i << endl;reset(&i);cout << "调用之后:\n" << "i=" << i << endl << "i的地址是" << &i << endl;
}


调用reset函数之后,实参所指的对象被置为0,但是实参本身并没有改变:

熟悉C的程序员常常使用指针类型的形参访问函数外部的对象。在C++语言中,建议使用引用类型的形参替代指针。
 

传引用参数

回忆过去所学的知识,我们知道对于引用的操作实际上是作用在引用所引的对象上

int n =0,i=42;int &r=n; //绑定了n(即r是n的另一个名字)r=42; //现在n的值是42
r=i; //现在n的值和i相同
i=r; // i的值和n相同


引用形参的行为与之类似。通过使用引用形参,允许函数改变一个或多个实参的值。

举个例子,我们可以改写上面的reset程序,使其接受的参数是引用类型而非指针:

#include<iostream>
using namespace std;
//该函数接受一个int对象的引用,然后将对象的值置为0
void reset(int& i)//i是传给reset函数的对象的另一个名字
{i = 0; //改变了i所引对象的值
}int main()
{int j = 42;cout << "j=" << j << endl;reset(j);cout << "j=" << j << endl;
}

调用这一版本的reset函数时,我们直接传入对象而无须传递对象的地址

在上述调用过程中,形参i仅仅是j的又一个名字。在reset内部对i的使用即是对j的使用。

和其他引用一样,引用形参绑定初始化它的对象。当调用这一版本的reset函数时,i绑定我们传给函数的int对象,此时改变i也就是改变i所引对象的值。

此例中,被改变的对象是传入reset的实参。


 

使用引用避免拷贝

拷贝大的类类型对象或者容器对象比较低效,甚至有的类类型(包括IO类型在内)根本就不支持拷贝操作。当某种类型不支持拷贝操作时,函数只能通过引用形参访问该类型的对象。

举个例子,我们准备编写一个函数比较两个string对象的长度。因为string对象可能会非常长,所以应该尽量避免直接拷贝它们,这时使用引用形参是比较明智的选择。又因为比较长度无须改变string对象的内容,所以把形参定义成对常量的引用:

//比较两个string对象的长度
bool isShorter(const string &sl, const string &s2) 
{
return sl.size() < s2.size();
}


 如果函数无须改变引用形参的值,最好将其声明为常量引用。

使用引用形参返回额外信息

一个函数只能返回一个值,然而有时函数需要同时返回多个值,引用形参为我们一次返回多个结果提供了有效的途径。

我们定义一个函数,求一个数/9和%9的值并返回。

该如何定义函数使得它能够既返回/9后的值又返回%9的值呢呢? 我们可以给函数定义一个新的数据类型,让它包含两个结果。

还有另一种更简单的方法,传入一个额外的引用实参,令其保存字符出现的次数:

#include<iostream>
using namespace std;int reset(int& i,int &w)
{int c = i % 9;w = i/9;return c;
}int main()
{int j = 42;int a;int s=reset(j,a);cout << s << endl;cout << a << endl;
}

这样子s存的就是j%9的值了,w存的是j/9的值了

const形参和实参

当形参是const时,必须要注意关干顶是const的讨论。如前所述,顶层const作用于对象本身:

const int ci = 42;//不能改变ci, const是顶层的
int i = ci;// 正确:当拷贝ci时,忽略了它的顶层const
int * const p= &i;//const是顶层的,不能给p赋值
*p=0; //正确:通过p改变对象的内容是允许的,现在i变成了0


和其他初始化过程一样,当用实参初始化形参时会忽略掉顶层const。

换句话说,形参的顶层const被忽略掉了。

当形参有顶层const时,传给它常量对象或者非常量对象都是可以的:

void fon(const int i) ( /* fcn能够读取i,但是不能向i写值*/)


调用 fcn函数时,既可以传入 const int也可以传入int。忽略掉形参的顶层const可能产生意想不到的结果;

void fcn(const int i) (/*fcn能够读取i,但是不能向i写值*/)
void fcn(int i) ( /*...*/)//错误:重复定义了fcn(int)


在C++语言中,允许我们定义若干具有相同名字的函数,不过前提是不同函数的形参列表应该有明显的区别。

因为顶层const被忽略掉了,所以在上面的代码中传入两个fcn函数的参数可以完全一样。

因此第二个fcn是错误的,尽管形式上有差异,但实际上它的形参和第一个fcn的形参没什么不同。

指针或引用形参与const

形参的初始化方式和变量的初始化方式是一样的,所以回顾通用的初始化规则有助于理解本节知识。我们可以使用非常量初始化一个底层const对象,但是反过来不行;同时一个普通的引用必须用同类型的对象初始化。

int i = 42;
const int *cp= bi;// 正确:但是cp不能改变i
const int &r = i; // 正确:但是r不能改变i
const int &r2=42;//正确:
int *p = cp; //错误:p的类型和cp的类型不匹配
int &r3 = r; //错误:r3的类型和r的类型不匹配
int &r4= 42; //错误:不能用字面值初始化一个非常量引用


将同样的初始化规则应用到参数传递上可得如下形式:

int i = 0;
const int ci = i;
string::size_type ctr =0;
reset(&i); 1/2调用形参类型是int*的reset函数
reset (&ci) ; //错误:不能用指向const int对象的指针初始化int*
reset (i) ; //调用形参类型是int&的reset函数
reset (ci) ; //错误:不能把普通引用绑定到const对象ci上
reset (42); //错误:不能把普通引用绑定到字面值上
reset(ctr); // 错误:类型不匹配,ctr是无符号类型


要想调用引用版本的reset,只能使用int类型的对象,而不能使用字面值、求值结果为int的表达式、需要转换的对象或者const int类型的对象。

类似的,要想调用指针版本的reset只能使用int*。

数组形参

数组的两个特殊性质对我们定义和使用作用在数组上的函数有影响,

这两个性质分别是:

  • 不允许拷贝数组
  • 使用数组时(通常)会将其转换成指针

因为不能拷贝数组,所以我们无法以值传递的方式使用数组参数。因为数组会被转换成指针,所以当我们为函数传递一个数组时,实际上传递的是指向数组首元素的指针。

尽管不能以值传递的方式传递数组,但是我们可以把形参写成类似数组的形式:

//尽管形式不同,但这三个print 函数是等价的
// 每个函数都有一个const int*类型的形参
void print(const int*);
void print(const int[]); //可以看出来,函数的意图是作用于一个数组
void print(const int[10]); // 这里的维度表示我们期望数组含有多少元素,实际不一定


尽管表现形式不同,但上面的三个函数是等价的:每个函数的唯一形参都是const int*类型的。

当编译器处理对print函数的调用时,只检查传入的参数是否是const int*类型:

int i = 0, j[2]={0,1};
print(&i); // 正确:&i的类型是int*
print(j); // 正确:j转换成int*并指向j[0]


如果我们传给print函数的是一个数组,则实参自动地转换成指向数组首元素的指针,数组的大小对函数的调用没有影响。

和其他使用数组的代码一样,以数组作为形参的函数也必须确保使用数组时不会越界。

管理指针形参

因为数组是以指针的形式传递给函数的,所以一开始函数并不知道数组的确切尺寸,调用者应该为此提供一些额外的信息。管理指针形参有三种常用的技术。


使用标记指定数组长度

管理数组实参的第一种方法是要求数组本身包含一个结束标记

使用这种方法的典型示例是C风格字符串。C风格字符串存储在字符数组中,并且在最后一个字符后面跟着一个空字符。函数在处理C风格字符串时遇到空字符停止

void print(const char *cp)
{
if (cp) // 若cp不是一个空指针
while (*cp) //只要指针所指的字符不是空字符
cout << *cp++; //输出当前字符并将指针向前移动一个位置
}


这种方法适用于那些有明显结束标记且该标记不会与普通数据混淆的情况,但是对于像int这样所有取值都是合法值的数据就不太有效了。

使用标准库规范

管理数组实参的第二种技术是传递指向数组首元素和尾后元素的指针。

这种方法受到了标准库技术的启发。使用该方法,我们可以按照如下形式输出元素内容:

void print(const int *beg, const int *end)
{
// 输出beg 到end之间(不含end)的所有元素
while (beg != end)
cout << *beg++ << endl; // 输出当前元素并将指针向前移动一个位置
}


while循环使用解引用运算符和后置递减运算符输出当前元素并在数组内将beg向前移动一个元素,当beg和end相等时结束循环。

为了调用这个函数,我们需要传入两个指针:一个指向要输出的首元素,另一个指向尾元素的下一位置:
 

int j[2]= {0, 1};
// j 转换成指向它首元素的指针
//第二个实参是指向j的尾后元素的指针print(begin(j),end(j)); // begin和end函数

只要调用者能正确地计算指针所指的位置,那么上述代码就是安全的。在这里,我们使用标准库begin和end函数提供所需的指针。

显式传递一个表示数组大小的形参

第三种管理数组实参的方法是专门定义一个表示数组大小的形参.
在C程序和过去的C++程序中常常使用这种方法。使用该方法,可以将print函数重写成如下形式:

// const int ia[]等价于const int* ia
// size表示数组的大小,将它显式地传给函数用于控制对 ia元素的访问
void print(const int ia[], size_t size)
{
for (size_t i = 0; i != size; ++i) 
{cout << iali] << endl;}
}

这个版本的程序通过形参size的值确定要输出多少个元素,调用print函数时必须传入这个表示数组大小的值:

int j[]={0,1 };//大小为2的整型数组
print(j.end(j)-begin(j));


只要传递给函数的size值不超过数组实际的大小,函数就是安全的。

数组形参和const

我们的三个print函数都把数组形参定义成了指向const的指针,关于引用的讨论同样适用于指针。

  • 当函数不需要对数组元素执行写操作的时候,数组形参应该是指向const的指针。
  • 只有当函数确实要改变元素值的时候,才把形参定义成指向非常量的指针。

数组引用形参

C++语言允许将变量定义成数组的引用,基于同样的道理,形参也可以是数组的引用。此时,引用形参绑定到对应的实参上,也就是绑定到数组上:

//正确:形参是数组的引用,维度是类型的一部分
void print(int (&arr)[10])
for (auto elem : arr)
cout << elem << endl;


&arr两端的括号必不可少:

f(int &arr[10]) //错误:将arr声明成了引用的数组
f(int (&arr)[10]) //正确:arr是具有10个整数的整型数组的引用


因为数组的大小是构成数组类型的一部分,所以只要不超过维度,在函数体内就可以放心地使用数组。但是,这一用法也无形中限制了print 函数的可用性,我们只能将函数作用于大小为10的数组:

int i= 0,j[2]={0, 1};
int k [10] = {0, 1, 2, 3, 4, 5, 6, 7,8, 9};
// 错误:实参不是含有10个整数的数组=
print (&i);
print(j); //错误:实参不是含有10个整数的数组
print(k); /1正确:实参是含有10个整数的数组


传递多维数组

我们曾经介绍过,在C++语言中实际上没有真正的多维数组,所谓多维数组其实是数组的数组。

和所有数组一样,当将多维数组传递给函数时,真正传递的是指向数组首元素的指针。

因为我们处理的是数组的数组,所以首元素本身就是一个数组,指针就是一个指向数组的指针。

数组第二维(以及后面所有维度)的大小都是数组类型的一部分,不能省略:

// matrix指向数组的首元素,该数组的元素是由10个整数构成的数组
void print (int (*matrix) [10], int rowsize) { /*...*/}


上述语句将matrix声明成指向含有10个整数的数组的指针。

再一次强调,*matrix两端的括号必不可少

int *matrix[10]; //10个指针构成的数组
int (*matrix)[10]; //指向含有10个整数的数组的指针


我们也可以使用数组的语法定义函数,此时编译器会一如既往地忽略掉第一个维度,所以最好不要把它包括在形参列表内:

// 等价定义
void print(int matrix[][10], int rowsize) /* ... */ 


matrix的声明看起来是一个二维数组,实际上形参是指向含有10个整数的数组的指针。

含有可变形参的函数

有时我们无法提前预知应该向函数传递几个实参。

例如,我们想要编写代码输出程序产生的错误信息,此时最好用同一个函数实现该项功能,以便对所有错误的处理能够整齐划一。然而,错误信息的种类不同,所以调用错误输出函数时传递的实参也各不相同。

为了编写能处理不同数量实参的函数,C++11新标准提供了两种主要的方法:

  1. 如果所有的实参类型相同,可以传递一个名为initializer_list的标准库类型;
  2. 如果实参的类型不同,我们可以编写一种特殊的函数,也就是所谓的可变参数模板。


C++还有一种特殊的形参类型(即省略符),可以用它传递可变数量的实参。本节将简要介绍省略符形参,不过需要注意的是,这种功能一般只用于与C函数交互的接口程序。

initializer_list形参

如果函数的实参数量未知但是全部实参的类型都相同,我们可以使用initializer_list类型的形参。

initializer_list是一种标准库类型,用于表示某种特定类型的值的数组。initializer_list类型定义在同名的头文件中,它提供的操作如表所示。

initializer_list<T> lst;默认初始化:T类型元素的空列表
initializer_list<T> lst{a,b,c...};

lst的元素数量和初始值一样多;

list的元素是对应初始值的副本;

列表中的元素是const

lst2(lst);

lst2=lst;

拷贝或赋值一个initializer_list对象不会拷贝列表中的元素:拷贝后,原始列表和副本共享元素
lst.size()列表中的元素数量
lst.begin()返回lst中首元素的指针
lst.end()返回lst中尾元素下一位置的指针

和vector一样,initializer_list也是一种模板类型。定义initializer_list对象时,必须说明列表中所含元素的类型:

initializer_list<string> ls; // initializer_list 的元素类型是 stringinitializer_list<int> li; // initializer_list的元素类型是int


和vector不一样的是,initializer_list对象中的元素永远是常量值,我们无法改变initializer_list对象中元素的值

我们使用如下的形式编写输出错误信息的函数,使其可以作用于可变数量的实参:

void error_msg(initializer_list<string> il)
{
for (auto beg = il.begin(); beg != il.end(); ++beg)
cout << beg<<"";
cout <<endl;
}


作用于initializer_list对象的begin和end操作类似于vector对应的成员。

begin()成员提供一个指向列表首元素的指针,end()成员提供一个指向列表尾后元素的指针。我们的函数首先初始化beg 令其表示首元素,然后依次遍历列表中的每个元素。在循环体中,解引用beg以访问当前元素并输出它的值。

传参

如果想向initializer_list形参中传递一个值的序列,则必须把序列放在一对花括号内

// expected和actual是string对象
if (expected != actual)
error_msg({"functionx", expected, actual});
else
error_msg({"functionx", "okay"});


在上面的代码中我们调用了同一个函数arrorms,但是两次调用传递的参数数量不同:第一次调用传入了三个值,第二次调用只传入了两个。

我们再看一个例子

#include<iostream>
using namespace std;
void A(initializer_list<int> i)//这个类似于标准库容器啊
{initializer_list<int>::iterator a= i.begin();cout << *a << endl;}int main()
{int a = 42;int b = 32;int c=9;int d = 11;A({ a, b, c, d });//只能传序列
//结果是42
}

含有initializer_list形参的函数也可以同时拥有其他形参。

#include<iostream>
using namespace std;void A(int w,initializer_list<int> i)
{initializer_list<int>::iterator a= i.begin();cout << *a << endl;}int main()
{int a = 42;int b = 32;int c=9;int d = 11;A(a,{ a, b, c, d });
}


省略符形参

省略符形参是为了便于C++程序访问某些特殊的C代码而设置的,这些代码使用了名为varargs的C标准库功能。通常,省略符形参不应用于其他目的。你的C编译器文档会描述如何使用varargs。

省略符形参应该仅仅用于C和C++通用的类型。特别应该注意的是,大多数类类型的对象在传递给省略符形参时都无法正确拷贝。

省略符形参只能出现在形参列表的最后一个位置,它的形式无外乎以下两种:

void foo(parm_list,...)
void foo(...);


第一种形式指定了foo函数的部分形参的类型,对应于这些形参的实参将会执行正常的类型检查。省略符形参所对应的实参无须类型检查。在第一种形式中,形参声明后面的逗号是可选的。
 

void B(...)
{;
}
int main()
{int a = 42;int b = 32;int c=9;B(a, b, c);
}

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

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

相关文章

Django缓存(一)

一、缓存的介绍 官网:Django 缓存框架 | Django 文档 | Django 为什么要什么缓存? 为了减少服务器的计算开销 Django框架自带有一个强大的缓存系统,可以保存动态页面,因此不必为每个请求计算它们。为了方便,Django提供不同级别的缓存粒度:可以缓存特定视图的输出,可以只…

Web核心简介

简介 web&#xff1a;全球广域网&#xff0c;也称万维网(www)&#xff0c;能够通过浏览器访问的网站 JavaWeb&#xff1a;是用Java技术来解决相关web互联网领域的技术栈 JavaWeb技术栈 B/S架构&#xff1a;Browser/Server&#xff0c;浏览器/服务器架构模式&#xff0c;它的…

走迷宫----bfs再矩阵图里的应用模版

对于之前走迷宫的那个题 回忆一下dfs的代码 #include <bits/stdc.h> using namespace std; int a[110][110]; bool check[110][110]; int n,m; int ans1e9; int nxt[4][2]{{1,0},{0,-1},{-1,0},{0,1}}; void dfs(int x,int y,int step){if(xn&&ym){ansmin(ans,…

IntelliJ IDEA集成git配置账号密码

1 背景说明 刚使用IDEA,本地也安装Git,在提交和拉取代码的时候,总提示登录框,而且登录框还不能输入账号密码,只能输入登录Token。如下: 从而无法正常使用IDEA的Git功能,很苦恼。 2 解决方法 2.1 安装Git 进入官网地址 https://git-scm.com/,点击下载: 浏览器直接…

机器学习算法那些事 | 使用Transformer模型进行时间序列预测实战

本文来源公众号“机器学习算法那些事”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;使用Transformer模型进行时间序列预测实战 时间序列预测是一个经久不衰的主题&#xff0c;受自然语言处理领域的成功启发&#xff0c;transfo…

WPS制作甘特图

“ 甘特图&#xff08;Gantt chart&#xff09;又称为横道图、条状图&#xff08;Bar chart&#xff09;&#xff0c;通过条状图来显示项目、进度和其他时间相关的系统进展的内在关系随着时间进展的情况。” 设置基础样式 设置行高 设置宽度 准备基础数据 计算持续时间 …

轻松引流几百精准粉丝,抖音自动爆粉秘籍揭秘

对于做互联网的朋友们来说&#xff0c;引流是一个必不可少的环节。 掌握一种优秀的引流方法至关重要&#xff0c;这也可以视为我们的生计之源。 今天&#xff0c;我将向大家介绍一款全自动的引流工具——抖音全自动引流脚本软件。 这款软件的效果非常显著&#xff0c;它可以替…

R-CNN笔记

目标检测之R-CNN论文精讲&#xff0c;RCNN_哔哩哔哩_bilibili 论文背景 在该论文提出之前&#xff0c;主流的目标检测思路是&#xff1a; 将一幅图片划分成很多个区域&#xff0c;单独提取出来 对于每个区域使用传统的特征提取方法提取 提取结束后可以使用以为特征向量表示 可以…

计算方法实验2:列主元消元法和Gauss-Seidel迭代法解线性方程组

Task 即已知 y 0 0 , y 100 1 y_00,y_{100}1 y0​0,y100​1&#xff0c;解线性方程组 A y b \mathbf{A}\mathbf{y} \mathbf{b} Ayb&#xff0c;其中 A 99 99 [ − ( 2 ϵ h ) ϵ h 0 ⋯ 0 ϵ − ( 2 ϵ h ) ϵ h ⋯ 0 0 ϵ − ( 2 ϵ h ) ⋯ 0 ⋮ ⋮ ⋱ ⋱ ⋮ 0 0 ⋯…

C++命名空间和内联函数

目录 命名空间 内联函数 概述 特性&#xff1a; 命名空间 在C/C中&#xff0c;变量&#xff0c;函数和和类这些名称都存在于全局作用域中&#xff0c;可能会导致很多冲突&#xff0c;使用命名空间的目的是对标识符的名称进行本地化&#xff0c;避免命名冲突或名字污染&…

C语言函数和数组

目录 一.数组 一.一维数组&#xff1a; 1.一维数组的创建: 2.一维数组的初始化&#xff1a; 3.一维数组的使用 4.一维数组在内存中的存储&#xff1a; 二.二维数组&#xff1a; 三.数组越界&#xff1a; 四.数组作为函数参数&#xff1a; 二.函数 一.函数是什么&…

vue3对openlayers使用(加高德,天地图图层)

OpenLayers认识 WebGIS四大框架&#xff1a; Leaflet、OpenLayers、Mapbox、Cesium OpenLayers 是一个强大的开源 JavaScript 地图库&#xff0c;专注于提供可嵌入网页的交互式地图体验。作为一款地理信息系统&#xff08;GIS&#xff09;的前端开发工具&#xff0c;OpenLaye…

关于php foreach函数和变量覆盖

foreach函数是PHP中用于遍历数组或对象的函数&#xff08;且仅用于数组的遍历&#xff09;。它允许循环遍历数组中的每个元素&#xff0c;并对每个元素执行相同的操作。foreach语句的基本语法如下&#xff1a; foreach ($array as $value) {//执行的操作 }在这个语法中&#x…

C++ Thread 源码 观后 自我感悟 整理

Thread的主要数据成员为_Thr 里面存储的是线程句柄和线程ID 先看看赋值运算符的移动构造 最开始判断线程的ID是否不为0 _STD就是使用std的域 如果线程ID不为0&#xff0c;那么就抛出异常 这里_New_val使用了完美转发&#xff0c;交换_Val和_New_val的值 _Thr _STD exchange(_…

回归预测 | Matlab基于SAO-LSTM雪消融算法优化长短期记忆神经网络的数据多输入单输出回归预测

回归预测 | Matlab基于SAO-LSTM雪消融算法优化长短期记忆神经网络的数据多输入单输出回归预测 目录 回归预测 | Matlab基于SAO-LSTM雪消融算法优化长短期记忆神经网络的数据多输入单输出回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab基于SAO-LSTM雪消融…

【Linux】进程的进一步认识

目录 进程的创建 fork函数初步认识 fork函数的返回值 写时拷贝 操作系统怎么知道什么时候要写时拷贝的呢&#xff1f; fork的常规用法 fork调用失败的原因 进程终止 进程的退出场景 进程常见退出方法 正常终止&#xff08;可以通过 echo $? 查看进程退出码&#xff…

Spring Boot从入门到实战

课程介绍 本课程从SpringBoot的最基础的安装、配置开始到SpringBoot的日志管理、Web业务开发、数据存储、数据缓存&#xff0c;安全控制及相关企业级应用&#xff0c;全程案例贯穿&#xff0c;案例每一步的都会讲解实现思路&#xff0c;全程手敲代码实现。让你不仅能够掌Sprin…

【Linux操作系统】:进程控制

目录 一、程序地址空间 1.C/C中的程序地址空间 2.进程地址空间 进程地址空间概念 什么是地址空间&#xff1f;什么是区域划分&#xff1f; 为啥要有地址空间&#xff1f; 地址空间的补充 二、进程创建 1.fork函数 2.写时拷贝 3.fork常规用法 4.fork调用失败的原因 …

Linux 常用命令 1

Tips&#xff1a;终端热键ctrl shift 放大终端窗口的字体 ctrl - 缩小终端窗口的字体 注意区分大小写 查阅命令帮助信息&#xff1a; 1&#xff09;--help command –help(两个减号) 显示command命令的帮助信息 2&#xff09;man man command 查阅command命令的使…

MyEclipse打开文件跳转到notepad打开问题

问题描述 windows系统打开README.md文件&#xff0c;每次都需要右键选择notepad打开&#xff0c;感觉很麻烦&#xff0c;然后就把README.md文件打开方式默认选择了notepad&#xff0c;这样每次双击就能打开&#xff0c;感觉很方便。 然后某天使用MyEclipse时&#xff0c;双击RE…