函数调用与参数传递

一、函数调用及返回值

对于有返回值的函数,调用时必须以值的形式出现在表达式中,比如下面程序第14行,因为Add()这个函数是有返回值,所以调用的时候是sum=Add();
第14行调用的时候Add(x,y),x和y为实际参数(argument),
第7行定义Add()时候是int Add(int a,int b), a和b为形式参数(parameter),
程序运行到第14行时,实际上进行了参数传递,也就是a=x,b=y;

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
/******************************************************************************
Add_function

*******************************************************************************/
#include<iostream>
using namespace std;
int Add(int a,int b){
    return a+b;
    }
int main(){
    int x,y,sum;
    cout<<"please input two integer number:";
    cin>>x>>y;
    sum=Add(x,y);
    cout<<"the sum of two number is "<<sum;
    
}

二、参数传递

在函数调用的时候采用的是值传递,形参取得了实参的值,但改变函数形参的值并不会影响外部实参的值。
实参就是在主调函数中的参数,形参这是被调函数中的参数。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/******************************************************************************
Swap_function

*******************************************************************************/
#include<iostream>
using namespace std;

void Swap (int a, int b){
  int t;
  t = a;
  a = b;
  b = t;
  cout << "the two number in Swap function:";
  cout << a << " " << b << endl;

}

int main (){
  int x, y;
  cout << "please input two number:";
  cin >> x >> y;
  Swap (x, y);
  cout << "the two number in main function:";
  cout << x << " " << y;

}

C++函数形态总共有以下四类:
1、返回类型 函数名(参数列表)
2、返回类型 函数名(无参数 )
3、无返回值 函数名(参数列表)
4、无返回值 函数名(无参数 )

1、有返回值,有参数。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#include<iostream>
using namespace std;
int add(int a,int b){
    return a+b;
}
int main(){
    int x,y,sum;
    cin>>x>>y;
    sum=add(x,y);
    cout<<sum; }

2、有返回值,无参数。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#include<iostream>
using namespace std;
int add(){
     int x,y;
    cin>>x>>y;
    return x+y;}
int main(){
    int sum;
    sum=add();
    cout<<sum;   }

3、无返回值,有参数。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#include<iostream>
using namespace std;
void add(int a,int b){
    cout<<a+b;
}
int main(){
    int x,y,sum;
    cin>>x>>y;
    add(x,y);
}

4、无返回值,无参数。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#include<iostream>
using namespace std;
void add(){
     int x,y,sum;
    cin>>x>>y;
    cout<<x+y;
}
int main(){
   add();
}

三、子函数调用子函数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#include<iostream>
using namespace std;

int myAbs(int n){
    if(n>0)return n;
    else return -n;
}
int Add(int a,int b){
    a=myAbs(a);
    b=myAbs(b);
    return a+b;
    }
int main(){
    int x,y,sum;
    cout<<"please input two integer number: ";
    cin>>x>>y;
    sum=Add(x,y);
    cout<<"the sum of two number is "<<sum;
    return 0;
}

三、函数的形参和实参具有以下特点:

1. 形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只有在函数内部有效。函数调用结束返回主调函数后则不能再使用该形参变量。

2. 实参是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使实参获得确定值。

3. 实参和形参在数量上,类型上,顺序上应严格一致,否则会发生类型不匹配”的错误。

4. 函数调用中发生的数据传送是单向的。即只能把实参的值传送给形参,而不能把形参的值反向地传送给实参。 因此在函数调用过程中,形参的值发生改变,而实参中的值不会变化。

形式参数就是定义函数时候的参数表,只是定义了调用时参数的个数、类型和用来引用的名字,并没有具体的内容。形参未被调用时,不占存储单元。形参只在调用过程中占用存储单元。

在调用函数时,给形参分配存储单元,实参不仅是常量、变量或者表达式,且要与形参类型一致!而且实参要有确定的值,在调用过程中实参将值赋给形参,并将实际参数对应的数值传递给形式参数;

当调用结束后,形参单元被释放,实参单元仍然保留 并且维持原值。所以说,实参是调用函数传递的具体数据。实参对形参数据传递时时单向传递。在存储单元中是不同的单元。

四、关于inline关键字

inline 关键字在 C++ 中是一个提示编译器的指令,它用于请求编译器将函数的调用替换为函数的实际代码,以减少函数调用的开销。具体来说,它的作用和原理如下:

1. 减少函数调用开销

通常,当你调用一个函数时,程序的控制权会跳转到函数的定义位置,执行完函数中的代码后,再跳回到调用函数的位置。这种过程涉及函数调用栈的管理,比如保存当前的执行状态、参数传递、跳转等,这会带来一定的开销。

使用 inline 关键字后,编译器会尝试在编译时直接用函数体替换每一个函数调用,而不是真正进行函数调用,从而消除这些额外的开销。

2. 编译器的自由裁量权

需要注意的是,inline 只是一个请求,编译器可以选择忽略这个请求。对于一些复杂的或递归的函数,编译器可能会拒绝将它们内联,而继续以普通的方式进行函数调用。

3. 代码膨胀风险

虽然内联函数可以减少函数调用的开销,但它会增加生成代码的大小(代码膨胀),因为每次调用函数时,函数体的代码都会被复制到调用点。因此,inline 通常适用于那些很小且频繁调用的函数,比如简单的 gettersetter 函数或单行表达式的函数。

4. inline 函数的定义

对于类成员函数,如果在类定义内部直接定义函数,编译器会默认将其视为 inline 函数。

class MyClass {
public:
    inline void myFunction() {
        // 这个函数通常会被编译器内联
    }
};

5. 作用范围

inline 的作用范围是全局的,这意味着如果在多个源文件中使用 inline 函数,编译器会将其视为同一个函数,并不会导致重复定义错误。

示例

inline int add(int a, int b) {
    return a + b;
}

int main() {
    int result = add(2, 3); // 这里编译器可能会直接将 add 函数体插入到调用点
    return 0;
}

在这个例子中,add 函数可能会被直接插入到 main 函数中的调用点,从而避免实际的函数调用。这提高了程序的执行效率,特别是在那些频繁调用的小函数场景下。

总结

inline 关键字用于请求编译器在函数调用点直接插入函数体代码,以减少函数调用的开销。但这个请求不一定会被编译器执行,并且需要小心使用以避免代码膨胀问题。

Scroll to Top