C++ Primer 学习笔记(5)——函数

本文深入讲解C++函数的定义、调用及参数传递方式。涵盖了形参与实参的概念、函数返回类型、形参表等内容,并通过实例演示了非引用形参、指针形参和引用形参的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.函数的定义

函数的调用

请参看以下程序:

#include <iostream>

using namespace std;

//return the GCD(greater common divisor)
int gcd(int v1, int v2)
{
    while(v2)
    {
        int temp = v2;
        v2 = v1 % v2;
        v1 = temp;
    }
    return v1;
}

int main()
{
    int a, b;
    cin>>a>>b;
    cout<<gcd(a,b)<<endl;
}
上述程序实现了求两数最大公约数的功能。

C++需使用调用操作符来实现函数的调用,如上程序中的gcd(a,b)中的"("和")"符号。该运算返回的结果就是函数的返回值。

当我们在调用gcd()函数时,第一件事是创建v1和v2的int型变量,并将这两个变量初始化为调用gcd时传递的实参值。上例中,v1的初值为i,而v2则初始化为j的值。

   1.形参和实参

形参为函数提供了已经命名的局部存储空间。它们之间的差别在于形参是在函数的形参表中定义的,并由调用函数时传递给函数的实参初始化。

实参是一个表达式,它可以是变量或者字面值常量,甚至是包含一个或者几个操作符的表达式。在调用函数时,所能传递的实参个数必须与函数的形参个数完全相同。实参的类型也要与其对应的形参的类型完全匹配

请注意:

1.实参必须要与形参类型相同;

2.实参或者可以与形参隐式转换。

   2.函数返回类型

bool is_present(int *, int);  //returns bool
int count(const string &, char);  //returns int
Date &calnedar(const char*);  //returns reference to Date
void process();  //process does not return a value

请注意

1.函数不能返回另一个函数或者内置数组类型,但是可以返回指向函数的指针或者指向数组元素的指针的指针:

如:

//pointer to first element of the array
int *foo_bar()
{
      /*...*/
}
2.函数必须指定返回类型(缺乏返回类型的函数将被假定为int型,仅限早期C++)。

   3.函数形参表

如第一例中,gcd函数:

gcd("hello","world");//wrong argument type
gcd(24312);//too few arguments
gcd(12,1,1);//too many arguments
都是不合法的。

而如下代码:

gcd(3.1,6.2);
却是合法的。编译器会把它变为:

gcd(3,6);

2.参数传递

非引用形参

非引用形参表示对应实参的局部副本,这类形参的修改仅仅改变了局部副本的值,一旦函数执行结束,这些局部变量的值也就没有了:
//return the GCD(greater common divisor)
int gcd(int v1, int v2)
{
    while(v2)
    {
        int temp = v2;
        v2 = v1 % v2;
        v1 = temp;
    }
    return v1;
}
如上例中的v1和v2。如果如下调用:
gcd(i,j);
i和j的值不受gcd内执行的赋值操作的影响。

   1.指针形参

函数的形参可以是指针,此时将复制实参指针。

请参看以下程序:

#include <iostream>

using namespace std;

void reset(int *ip)

{
    *ip = 0; // changes the value of the object to which ip points
    ip = 0; // changes only the local value of ip; the argument is unchanged
}
int main()
{
    int i = 42;
    int *p(&i);
    cout << "i: " << *p << '\n'; // prints i: 42
    reset(p); // changes *p but not p
    cout << "i: " << *p << endl; // ok: prints i: 0
}

上述程序实现了如下功能:

1.新建一个指针p,把它的值初始化为i的地址,即让p指向i;

2.输出p指针指向的地址的值;

3.reset函数的目的是,让p指针指向的地址的内容归零,并让p指空;

4.输出指空之后的p指针指向的地址的值。


复制实参的局限性

复制实参并不是在所有的情况下都适合,不适宜复制实参的情况包括:

• 当需要在函数中修改实参的值时。

• 当需要以大型对象作为实参传递时。对实际的应用而言,复制对象所付出的时间和存储空间代价往往过大。

• 当没有办法实现对象的复制时。


对于上述几种情况,有效的解决办法是将形参定义为引用或指针类型。


请再看以下程序:

#include <iostream>

using namespace std;

void swap(int v1, int v2)
{
    int tmp = v2;
    v2 = v1; // assigns new value to local copy of the argument
    v1 = tmp;
} // local objects v1 and v2 no longer exist
int main()
{
    int i = 10;
    int j = 20;
    cout << "Before swap():\ti: "
         << i << "\tj: " << j << endl;
    swap(i, j);
    cout << "After swap():\ti: "
         << i << "\tj: " << j << endl;
    return 0;
}

它并没有实现交换两个量的值的目的,为什么呢?因为它在swap函数进行时,只是交换了形参的值,对实参并无影响。

要想实现如何操作?

请如下更改:

#include <iostream>

using namespace std;

void swap(int &v1, int &v2)
{
    int tmp = v2;
    v2 = v1;
    v1 = tmp;
}

改变v1,v2的地址来实现交换。

ps,如下语句也可以交换。。。

#include <iostream>

using namespace std;

int main()
{
    int i = 10;
    int j = 20;
    cout << "Before swap():\ti: "
         << i << "\tj: " << j << endl;
    i ^= j ^= i ^= j;
    cout << "After swap():\ti: "
         << i << "\tj: " << j << endl;
    return 0;
}

   2.使用引用形参返回额外的信息


#include <iostream>
#include <vector>

using namespace std;

// returns an iterator that refers to the first occurrence of value
// the reference parameter occurs contains a second return value
vector<int>::const_iterator find_val(
    vector<int>::const_iterator beg, // first element
    vector<int>::const_iterator end, // one past lastelement
    int value, // the value we want
    vector<int>::size_type &occurs) // number of times it occurs
{
// res_iter will hold first occurrence, if any
    vector<int>::const_iterator res_iter = end;
    occurs = 0; // set occurrence count parameter
    for ( ; beg != end; ++beg)
        if (*beg == value)
        {
            // remember first occurrence of value
            if (res_iter == end)
            {
                res_iter = beg;
            }
            ++occurs; // increment occurrence count
        }
    return res_iter; // count returned implicitly in occurs
}
int main()
{
    vector<int> vec;
    //input data
    int n;
    cin>>n;
    while(n--)
    {
        int i;
        cin>>i;
        vec.push_back(i);
    }
    
    int a;
    cin>>a;//the value you want to find
    vector<int>::const_iterator it;
    vector<int>::size_type occurence;
    it = find_val(vec.begin(),vec.end(),a,occurence);
    cout<<*it<<"\t"<<occurence<<endl;
}
说明:

调用 find_val 时,需传递四个实参:一对标志 vector 对象中要搜索的元素范围的迭代器,所查找的值,以及用于存储出现次数的size_type 类型对象。

如果出现了:

1.it返回的值是其第一次出现的数组位置

2.occurence的值是出现次数。


   3.使用 const 指针避免复制操作

请参看以下程序,其功能是比较两字符串长度。
// compare the length of two strings
bool isShorter(const string &s1, const string &s2)
{
return s1.size() < s2.size();
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值