您的位置:首页 > 编程语言 > C语言/C++

c++学习笔记之函数的调用和返回

2011-08-27 17:31 549 查看
    准备花三天时间来好好谢谢c++函数的调用和返回。当然这里参照网络的,还有一些书,来进行笔记。本章节分为
1、声明参数和返回类型
       函数是由返回类型,函数名,和函数名后边括号内的形式参数列表组成的。例如 :
    voidf(int a);//函数的声明, 不会返回值 void
    int g(int b,int c){return a*b;}//函数的定义
函数的定义包括大括号,以及在内部要执行的一些动作。函数返回类型为void时候,表示什么也不做。
    在函数声明和定义中,你可以为参数命名也可以不命名,完全取决你需要。
    如下面的函数 int my_find(vector<string>  vs,string s,int hint);//有参数名字的
    也可以这么声明   int my_find(vector<string> ,string ,int );     //无参数的。
但是,有参数命名的我们看了好看,习惯这么写。
当然我们在定义一个函数的时候是要写形参参数的。
//查找s在vs中
 
int my_find(vector<string> vs,string s,int hint)

{

if(hint<0||vs.size()<hint) hint=0;

for(int i=hint;i<vs.size();i++)

{

if(vs[i]==s) return i;

if(0<hint)

{

for(int i=0;i<vs.size();i++)

if(vs[i]==s)        return i;

}

}

return -1;

}


从这个函数我们发现,这个int对我们的使用,让我们的这个函数产生了复杂的效果,我们并不想用它,但是,我们又不打算更改这个函数的声明方式。所以这个时候我们也可以这么写
int my_find(vector<string> vs ,string s,int )

{

for(int i=0;i<vs.size();i++)

{

if(vs[i]==s) retrun i;

retrun -1;

}

}


           
2、返回一个值
    我们可以用return 返回一个值
     
T Fun()

{

V v;

return v;

}


T t=Fun();


这段代码我们可以看到,我们利用函数Fun()来初始化了值,也就是说 返回值可以作为变量初始化的一种形式。如果函数声明要返回一个值,那么函数体内一定要有个return 返回一个值,否则编译时就会报错;
double my_abs(int x)

{

if (x<0)

return -x;

else if (x>0)

return x;

}


尤其注意点的就是我们再利用vs,vc编程到时候返回值,是有所不同的。vs一般都是返回一个int值,
上例子中,当我们x=0时,就会报错了。没有返回值
3、传值参数与引用参数
这一节,以及下一节都是我要重点要讲述的内容,因为它涉及了引用,在C++中,引用的使用是关系到了c++程序的效率等问题。
想函数传递参数是最简单的方式是,将参数的值拷贝一份,传递给函数,一个函数的f()的参数实际是函数的局部变量如下变得的例子就一目了然了
#include "stdafx.h"

#include <vector>

#include <iostream>

using namespace std;

int func(int x)

{

return x+1;

}

int _tmain(int argc, _TCHAR* argv[])

{

int x1=2;

cout<<func(x1)<<endl;

cout<<"x1="<<x1<<endl;

int x2=8;

cout<<func(x2)<<endl;

cout<<"x2="<<x2<<endl;

}


 

我们发现x1,x2的值并没有改变, 说明参数是通过拷贝一份的值传给他的。
如图


直接就是拷贝值。



4、传常量引用参数
    当我们传的值是一个比较小的数字,或者字符,这时候,拷贝的代价并不大,占用的系统资源就比较少,但是当我们传递一个表的数据,一个图像等等大容量的数据呢?如果再拷贝的话,就会对系统资源造成极大浪费。而且对效率也是问题,
例如下边例子
void  print(vector<double> v)

{

cout<<"{";

for(int i=0;i<v.size();i++)

{

cout<<v[i];

if(i!=v.size()-1) cout<<",";

}

cout<<"}\n";

}

void f(int x)

{

vector<double> vd1(10);

vector<double> vd2(10000000);

vector<double> vd3(x);

print(vd1);

print(vd2);

print(vd3);

}


从以上例子可以看出,一个double如果按照八字节算,第一个是80,第二个八百万。如果x很大呢?这就会造成极大了浪费。
这个时候我们就开始使用下边对函数print改一下
void print(const vector<double> &v)

{

cout<<"{";

for(int i=0;i<v.size();i++)

{

cout<<v[i];

if(i!=v.size()-1) cout<<",";

}

cout<<"}\n";

}

首先看一下例子
void init(vector<double> & v)

{

for(int i=0;i<v.size();i++)

v[i]=i;

}


引用了,引用其实就是一个变量的别名机制,给他起个名字,操作的时候就是对本身进行操作。
这时候我们就希望能够修改v值,进行初始化。引用允许我们对一个对象起一个新名字,例如int& 是对一个整形对象的一个引用,因此,我们可以利用以下代码:int i=7;
int & ii=i;

ii=10;

cout<<ii<< "  "<<i<<endl; //此时输出的是 10 10


通过实例可以看书,任何对引用进行修改的,就是对对象本身修改的。
应用的一个用途就是作为简写形式,例如以下形式,
vector<vector<double> > v;当我们多次使用某个向量时v[g(x)][f(x)]的时候,我们当然不愿意写这么表达式,所以我们可以这么写 double val=v[g(x)][f(x)];
但是当我们不仅需要对其读取值,还要对其进行写值的时候,这时候引用就派上用场了,我们可以如下声明,double& val=v[g(x)][f(x)],下面就会有一个经典的例子。

就是交换数的例子,上源代码

void swap1(int a,int b)

{

int temp=a;

a=b;

b=temp;

}

void swap2(int& a,int& b)

{

int temp=a;

a=b;

b=temp;

}

int _tmain(int argc, _TCHAR* argv[])

{

int x=2;

int y=3;

swap1(x,y);

cout<<"x="<<x<<endl;

cout<<"y="<<y<<endl;

int m=4;

int n=5;

swap2(m,n);

cout<<"m="<<m<<endl;

cout<<"n="<<n<<endl;

}


输出的结果为:
如图


就可以看出,利用引用才能进行对值的交换。

这时候大家注意上一个例子的参数列表,多出了个const,因为我们的引用是直接对对象本身操作的,如果你怕在调用的时候对对象不小心的修改,那么你就对这个参数进行const修饰,当你不小心对其修改了,那么编译器就会报出错误的。
5、传值和传引用的比较
       我们如何在传值参数,传引用参数和传常量应用参数中选择呢?
        下面我们有如下原则:
使用传值方式是是传的很小的参数,对象。
使用传常量引用方式传递你不需要修改的大对象
让函数返回一个值,而不是修改通过引用参数传递来的对象
只有迫不得已的时候才使用传引用方式。
当我们看到函数参数是以一个非常量引用参数传过来的参数,那我们必须假设该函数要进行对其修改。
考虑如下代码
 
int incr1(int x) {retrun x+1;}

void incr2(int &x){ x++;}

int m=2;

m=incr1(m);

incr2(m);


    这时候你会想到,效果一样,为什么还需要引用呢,但是一下情况你要知道:
用于操作容器
用于改变多个对象的函数   
下面使用一个函数说明一下
void  larger(vector<double> v1,vector<double> v2)

{

if(v1.size()!=v2.size()) error ("different size");

for(int i=0;i<v1.size();i++)

{

if(v1[i]<v2[2])

swap(v1[i],v2[2]);

}

}


先讲这些,如果有什么漏洞希望大家指出了。
         
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息