引用函数函数模板
一、引用
1.创建引用变量
c和c++使用&
符合来表示指示变量的地址,c++给&
符合赋予了另一个含义,将其用来声明引用,例如:将rodents作为rats变量的别名:
int rats;
int & rodents = rats;
//&不是地址运算符,而是类型标识的一部分。
//就像声明中的`char*`指的是指向char的指针一样,`int&`指的是指向int的引用。
实例:
#include <iostream>
using namespace std;
int main()
{
int rats=101;
int & rodents=rats;
cout<<"rats="<<rats;
cout<<",rodents="<<rodents<<endl;
rodents++;
cout<<"rats="<<rats;
cout<<",rodents="<<rodents<<endl;
cout<<"rats address="<<&rats;
cout<<",rodents adderss= "<<&rodents<<endl;
return 0;
}
注:
&
运算符不是地址运算符,而是将rodents得类型声明为int&
,即指向int的变量的引用。- 声明引用时将其初始,而不能像指针那样,先声明后,再赋值。(重要)
2.将引用用作函数参数
- 引用经常被用作函数参数,使得函数中的变量名成为调用程序中的变量的别名。
- 这种传递参数的方法称为按引用传递。按引用传递允许被调用的函数能够访问调用函数中的变量。
实例:
#include <iostream>
using namespace std;
void swapr(int & a,int & b);
void swapp(int * p,int * q);
void swapv(int a,int b);
int main()
{
int wallet1=300;
int wallet2=350;
cout<<"wallet1= $"<<wallet1;
cout<<"wallet2= $"<<wallet2;
cout<<"Using references to swap contents:"<<endl;
swapr(wallet1,wallet2);
cout<<"wallet1= $"<<wallet1;
cout<<",wallet2= $"<<wallet2<<endl;
cout<<"Using pointers to swap contents again:"<<endl;
swapp(&wallet1,&wallet2);
cout<<"wallet1= $"<<wallet1;
cout<<",wallet2= $"<<wallet2<<endl;
cout<<"Trying to use passing by value:"<<endl;
swapv(wallet1,wallet2);
cout<<"wallet1= $"<<wallet1;
cout<<",wallet2= $"<<wallet2<<endl;
return 0;
}
void swapr(int & a,int & b)//引用传递
{
int temp;
temp=a;
a=b;
b=temp;
}
void swapp(int * p,int * q)//指针传递
{
int temp;
temp=*p;
*p=*q;
*q=temp;
}
void swapv(int a,int b)//普通传递
{
int temp;
temp=a;
a=b;
b=temp;
}
3.引用作为函数的返回值
引用作为函数返回值时,不能返回局部数据(例如局部变量、局部对象、局部数组等)的引用。
#include <iostream>
using namespace std;
int &my_arr(void)
{
int num=200;
return num;//函数返回什么变量,引用就是该变量的别名
//函数的返回值是引用时,不要返回局部变量
}
int &my_arr1(void)
{
static int num=100;
return num;
}
int main()
{
int &pt=my_arr();
//cout<<"pt="<<pt<<endl;非法访问
int &pt1=my_arr1();
cout<<"pt1="<<pt1<<endl;
}
当函数返回值作为左值 那么函数的返回值类型必须是引用。
#include <iostream>
using namespace std;
int& my_arr(void)
{
static int num=100;
cout<<"num="<<num<<endl;
return num;
}
int main()
{
//函数的返回值,作为左值
my_arr()=5000;
my_arr();
}
4.引用给数组取别名
//方法1:
#include <iostream>
using namespace std;
int main()
{
int arr[5]={1,2,3,4,5};
int (&my_arr)[5]=arr;
int i=0;
for(i=0;i<5;i++)
cout<<my_arr[i]<<" "<<endl;
}
//方法2:和typedef一起使用
#include <iostream>
using namespace std;
int main()
{
int arr[5]={1,2,3,4,5};
typedef int Pn[5];//用typedef给数组arr取别名
//Pn就是数组的类型(5个int元素);
//my_arr数组的别名
Pn &my_arr=arr;
int i=0;
for(i=0;i<5;i++)
cout<<my_arr[i]<<" "<<endl;
}
5.常引用
#include <iostream>
using namespace std;
typedef struct
{
int num;
char name[32];
}STU;
void my_arr(STU tmp)//普通结构体变量作为形参,开销太大
{
cout<<"学号:"<<tmp.num<<",姓名:"<<tmp.name<<endl;
}
void my_arr1(const STU &tmp)//tmp为常引用
{
//tmp.num=2000;没有加const,num能修改值,加const不能
cout<<"学号:"<<tmp.num<<",姓名:"<<tmp.name<<endl;
}
int main()
{
STU pn={12,"Tom"};
my_arr1(pn);//传引用不需要修改pn
}
常量引用:
-
常量引用的定义格式:
const Type& ref = val;
-
常量引用注意: 字面量不能赋给引用,但是可以赋给 const 引用 const 修饰的引 用,不能修改。
实例:
#include <iostream>
using namespace std;
int main()
{
//给常量10取个别名:pn
//int &针对是int,10是const int类型
//const int 针对的是const int,10是const int类型。
const int & pn=20;
cout<<"pn="<<pn<<endl;
}
6.将引用用于结构
使用结构引用参数的方式与使用基本变量引用相同。只需在声明结构参数时使用引用运算符&即可。如:
struct free_throws
{
string name;
int made;
int attempts;
float percent;
};
则可以这样编写函数原型,在函数中将指向该结构的引用作为参数:
void set_pc(free_throws & ft);
//防止函数修改传入的结构,可使用const :
void display(const free_throws & ft);
实例:
#include<iostream>
#include<string>
using namespace std;
struct free_throws {
string name;
int made;
int attempts;
float percent;
};
void set_pc(free_throws& ft);
void display(const free_throws& ft);
free_throws& accumulate(free_throws& target, const free_throws& source);
int main() {
free_throws one = { "Ifelsa Branch",13,14 };
free_throws two = { "Andor Knott",10,16 };
free_throws three = { "Minnie Max",7,9 };
free_throws four= { "Whily Looper",5,9 };
free_throws five= { "Long Long",6,14 };
free_throws team = { "Throwgoods",0,0 };
free_throws dup;
set_pc(one);
display(one);
accumulate(team, one);
display(accumulate(team, two));
accumulate(accumulate(team, three), four);
display(team);
dup = accumulate(team, five);
cout << "Displaying team:\n";
display(team);
cout << "Display dup after assignment:\n";
display(dup);
set_pc(four);
accumulate(dup, five) = four;
cout << "Displaying dup after ill-advised assignment:\n";
display(dup);
return 0;
}
void set_pc(free_throws& ft)
{
if (ft.attempts != 0)
ft.percent = 1000.0f * float(ft.made) / float(ft.attempts);
else
ft.percent = 0;
}
//此函数形式结构的内容,而不修改它,因此使用了一个const引用参数,也可以按值传递结构,但与复制原始结构的拷贝相比,使用引用节省时间与内存。
void display(const free_throws& ft)
{
cout << "Name:" << ft.name << endl;
cout << "Made:" << ft.made << endl;
cout << "Attempts:" << ft.attempts << endl;
cout << "Percent:" << ft.percent << endl;
}
free_throws& accumulate(free_throws& target, const free_throws& source)
{
target.attempts += source.attempts;
target.made += source.made;
set_pc(target);
return target;
}
set_pc(one);
-
函数
set_pc()
的形参ft为引用,因此ft执行one,函数set_pc
的代码设置成员one.percent
。 -
这里按值传递不行,因此将导致设置的是one的临时拷贝的成员percent。
-
另一种方法:使用指针参数并传递地址:
set_pc(&one);
...
void set_pc(free_throws * pt)
{
if(pt->attempts !=0)
pt->percent = 100.0f*float(pt->made)/float(pt->attempts);
else
pt->percent = 0;
}
accumulate(team,one);
此函数接受两个结构参数,并将第二个结构的成员attempts和made的数据加到第一个结构相应成员中。只修改了第一个结构,因此第一个参数为引用,而第二个参数为const引用:
free_throws & accumulate(free_throws & target,const free_throws & source);
返回值呢?可以将返回值声明为void,但有函数调用:
display(accumulate(team,two));
//此函数将结果对象team作为第一个参数传递给accumulate()。意味着在函数accumulate()中,target指向的是team。
//函数accumulate()修改team,再返回指向它的引用。
注意返回语句:
return target;
如果返回类型被声明为free_throws而不是free_throws &,上述语句将返回target(也就是team)的拷贝,但返回类型为引用,意味着返回的是最初传递给accumulate()的team()对象。
将accumulate()
的返回值作为参数传递给了display()
,这意味着将team传递给了display()
。 display()的参数为引用,这意味着函数display()
中的ft指向的是team,因此将显示team的内容。所以,下述代码:
display(accumulate(team,two));
//与下面代码等效:
accumulate(team,two);
display(team);
上述逻辑也适用于下面语句:
accumulate(accumulate(team,three),four);
//该语句与下面等效:
accumulate(team,three);
accumulate(team,four);
下面是赋值语句:
dup = accumulate(team,five);//将team中的值赋值到dup中。
accumulate(dup,five) = four;
//将值赋值给函数调用,可行的,因为函数的返回值是一个引用。
//若函数`accumulate()`按值返回,这条语句不能通过。由于返回的是指向dup的引用,上述代码于下面等效:
accumulate(dup,five);
dup = four;
//其中第二条语句消除了第一条所做的工作,因此在原始赋值语句使用accumulate()的方式并不好。
7. 为何要返回引用
传统返回机制与按值传递函数参数类似:计算关键字return后面的表达式,并将结果返回给调用函数。从概念上说,这个值被复制到一 个临时位置,而调用程序将使用这个值。请看下面的代码:
double m = sqrt(16.0);//值 4.0 被复制到一 个临时位置,然后被复制给 m 。
cout<<sqrt(25.0);//值 5.0 被复制到一 个临时位置,然后被传递给 cout
//实际上,编译器可能合并某些步骤。
dup = accumulate(team,five);
//若accumulate()返回一 个结构,而不是指向结构的引用,将把整个结构复制到一 个临时位置,再将这个拷贝复制给dup。
//但在返回值为引用时,将直接把team复制到dup, 其效率更高。
注:返回应用的函数实际上是被引用的变量的别名。
8.返回引用时注意的问题
返回引用最重要的一点是,应避免返回函数终止时不再存在的内存单元引用。应避免编写下面的代码:
const free_throws & clone2(free_throws & ft){
free_throws newguy;//错误的第一步
newguy = ft;//复制信息
return newguy;//返回对副本的引用
}
-
该函数返回一 个指向临时变量 (newguy) 的引用,函数运行完毕后它将不再存在。同样,也应避免返回指向临时变量的指针。
-
为避免这种问题,最简单的方法是,返回一 个作为参数传递给函数的引用。作为参数的引用将指向调用函数使用的数据,因此返回的引用也将指向这些数据。accumulate()正是这样做的。
-
另一 种方法是用 new 来分配新的存储空间。前面见过这样的函数,它使用 new 为字符串分配内存空间,并返回指向该内存空间的指针。下面是使用引用来完成类似工作的方法:
const free_thorws & clone(free_throws & ft)
{
free_throws * pt;
*pt = ft;
return *pt;
}
第一 条语句创建一 个无名的 free_throws结构,并让指针pt指向该结构,因此*pt
就是该结构。上述代码似乎会返回该结构,但函数声明表明,该函数实际上将返回这个结构的引用。这样,便可以这样使用该函数:
free_throws & jolly = clone(three);
这使得jolly
成为新结构的引用,这种方法存在一个问题:
-
在不再new分配的内存时,应使用delete来释放它们。
-
调用clone()隐藏了对new的调用,这使得以后很容易忘记使用delete来释放内存。
-
后面讨论的auto_ptr模板以及C++11新增的
unique_ptr
可帮助程序员自动完成释放工作。
9.为何将const用于引用返回类型
例:
accumulate(dup,five) = four;
-
首先将five的数据添加到dup中,再使用four的内容覆盖dup的内容。这条语句为何能够通过编译呢?在赋值语句中,左边必须是可修改的左值。
-
在赋值表达式中,左边的子表达式必须标识一 个可修改的内存块。在这里,函数返回指向dup 的引用,它确实标识的是一 个这样的内存块,因此这条语句是合法的。
-
另一 方面,常规 (非引用)返回类型是右值:不能通过地址访问的值。这种表达式可出现在赋值语句的右边,但不能出现在左边。
-
其他右值包括字面值(如10.0)和表达式(如 x+ y)。显然,获取字面值(如10.0)的地址没有意义,但为何常规函数返回值是右值呢?这是因为这种返回值位于临时内存单元中,运行到下 一 条语句时,它们可能不再存在。
假设您要使用引用返回值,但又不允许执行像给accumulate()赋值这样的操作,只需将返回类型声明为const引用:
const free_throws & accumulate(free_throws & target,const free_throws & source);
现在返回类型为const, 是不可修改的左值,因此下面的赋值语句不合法:
accumulate(dup,five) = four;//不允许const引用返回
该程序中的其他函数调用又如何呢?返回类型为const引用后,下面的语句仍合法:
display(accumulate(team, two)) ;
这是因为display()的形参也是const free_throws&
类型。下面的语句不合法,因此accumulate()的第一个形参不是const:
ccumulate(accumulate(team, three), four);
这影响大吗?就这里而言不大,因为仍可以这样做:
accumulate(team, three);
accumulate(team, four);
- 仍可以在赋值语句右边使用accumulate()。
- 通过省略const, 可以编写更简短代码,但其含义也更模糊。
- 常,应避免在设计中添加模糊的特性,因为模糊特性增加了犯错的机会。将返回类型声明为const引用,
10.将引用用于类对象
将类对象传递给函数时,c++通常的做法是使用引用。让string ostream istream ofstream 和ifstream
等类的对象作为参数,例使用string类:
#include <iostream>
#include<string>
using namespace std;
string version1(const string &s1,const string & s2);
const string & version2(string & s1,const string & s2);
const string & version3(string & s1,const string & s2);
int main()
{
string input;
string copy;
string result;
cout<<"Enter a string:";
getline(cin,input);
copy=input;
cout<<"Your string as entered: "<<input<<endl;
result=version1(input,"***");
cout<<"Your string enhanced :"<<result<<endl;
cout<<"Your original string:"<<input<<endl;
result=version2(input,"###");
cout<<"Your string enhanced:"<<result<<endl;
cout<<"Your original string:"<<input<<endl;
cout<<"Resetting original string"<<endl;
input=copy;
result=version3(input,"@@@");
cout<<"Your string enhanced:"<<result<<endl;
cout<<"Your original string:"<<input<<endl;
return 0;
}
string version1(const string &s1, const string &s2)
{
string temp;
temp=s2+s1+s2;
return temp;
}
const string & version2(string &s1, const string &s2)
{
s1=s2+s1+s2;
return s1;
}
const string & version3(string &s1, const string &s2)
{
string temp;
temp=s2+s1+s2;//相加得到新字符串
return temp;
}
11.引用的属性和特别之处
使用引用参数时,需要了解些特点。例:使用两个函数计算参数的立方,其中一个函数接受double类型的参数,另一个接受double引用。
#include<iostream>
#include<climits>
using namespace std;
double cube(double a);
double refcube(double &ra);
int main()
{
double x =3.0;
cout<<cube(x);
cout<<"=cube of "<<x<<endl;
cout<<refcube(x);
cout<<"= cube of "<<x<<endl;
return 0;
}
double cube(double a)
{
a*=a *a;
return a;
}
double refcube(double &ra)
{
ra *=ra * ra;
return ra;
}
- refcube()函数修改了main()中的x值,而cube()没有,表明为何通常按值传递。
- 变量a位于cube()中,它被初始化为x的值,但修改了a并不会影响x。但由于refcube()使用引用参数,因此修改了ra实际上就是修改x。
- 如果想让函数使用传递给它的信息,而不对这些信息进行修改,同时又想使用引用,则应使用常量引用。例:在这个例子中,应在函数原型和函数头中使用const:
double refacube (const double &ra);
- 如果使用基本数值类型,应采用按值传递的方式,而不用按引用传递的方式。数据大时,引用参数将很有用。
按值传递可使用多种类型的实参。例如:
double z = cube(x+2.0);//传递值
z=cube(8.0);
int k = 10;
z=cube(k);//k转换为double,传值
double yo[3] ={2.2,3.3,4.4};
z=cube(yo[2]);//传递值4.4
如果传递给接受引用参数的函数,将会更严格。例:如果ra是个变量的别名,则实参应是变量。下面代码不合理,因为表达式x+3.0并不是变量:
double z = refcube(x+3.0);
如果试图使用refcube(x+3.0)函数调用,将发出警告。
例如:不能将值赋给该表达式:
x+3.0 = 5.0;//无意义
12.对象、继承和引用
-
ostream和ofstream类
凸显了引用的一个有趣属性,正如前面介绍的ofstream对象可以使用ostream类的方法,这使得文件输入/输出的格式与控制台输入/输出相同。 -
使得能够将特性从一 个类传递给另一 个类的语言特性被称为继承,这将在后面详细讨论。简单地说,ostream是基类(因为ofstream是建立在它的基础之上的),而ofstream是派生类(因为它是从ostream派生而来的)。
-
派生类继承了基类的方法,这意味着ofstream对象可以使用基类的特性,如格式化方法
precision()和setf()
。 -
继承的另 一 个特征是,基类引用可以指向派生类对象,而无需进行强制类型转换。这种特征的一 个实际结果是,可以定义 一 个接受基类引用作为参数的函数,调用该函数时,可以将基类对象作为参数,也可以将派生类对象作为参数。
-
例如,参数类型为
ostream&
的函数可以接受ostream对象(如cout)或您声明的 ofstream 对象作为参数。
下面程序通过调用同一 个函数 (只有函数调用参数不同)将数据写入文件和显示到屏幕上来说明了这一 点。该程序要求用户输入望远镜物镜和一 些目镜的焦距,然后计算并显示每个 目镜的放大倍数。放大倍数等于物镜的焦距除以目镜的焦距,因此计算很简单,该程序还使用一些格式化方法,这些方法用于cout和ofstream对象(在这个例子中是fout)时作用相同。
#include<iostream>
#include<fstream>
#include<cstdlib>
using namespace std;
void file_it(ostream & os, double fo, const double fe[] , int n);
const int LIMIT= 5;
int main()
{
ofstream fout;
const char * fn = "ep-data.txt";
fout.open(fn) ;
if(!fout.is_open())
{
cout<<"Can't open"<<fn<<".Byb.\n";
exit(EXIT_FAILURE);
double objective;
cout<<"Enter the focal length of you telescope objective in mm:";
cin>>objective;
double eps[LIMIT];
cout<<"Enter the focal lengths,in mm,of"<<LIMIT<<"eyepieces:\n";
for(int i=0;i<LIMIT;i++)
{
cout<<"Eyepiece#"<<i+1<<": ";
cin>>eps[i];
}
file_it(fout,objective,eps,LIMIT);//目镜数据写入ep_data.txt;fout的设置被修改,然后被恢复
file_it(cout,objective,eps,LIMIT);//将同样信息以同样地格式显示到屏幕上;cout的设置被修改,然后被恢复
cout<<"Done\n";
return 0;
}
}
void file_it(ostream & os,double fo,const double fe[],int n)
{
ios_base::fmtflags initial;//存储这种信息所需的数据类型名称
initial= os.setf(ios_base::fixed); //保存参数格式化状态;将对象置于使用定点表示的模式
os.precision(0);
os << "Focal length of objective: 11" << fo << "11 mm\n";
os.setf(ios::showpoint);//将对象显示为小数点的模式即使小数部分为0
os.precision(1);//显示多少位小数
os.width(12) ;
os<< "nf.1. eyepiece" ;
os.width(15);
os<<"magnification"<<endl;
for(int i =0;i<n;i++)
{
os.width(12);
os << fe[i] ;
os. width(15) ;
os << int(fo/fe[i] + 0.5) << endl;
}
os.setf(initial);//恢复初始格式化状态
}
运行:
13.临时变量、引用参数和const
若实参于引用参数不匹配,c++将生成临时变量。当前仅当参数为const引用时,C++才允许这样做,但以前不是,什么时候,c++生成临时变量,以及为何对const引用的限制是合理的。
首先,什么时候将创建临时变量?如果引用参数是const,则编译器将在下面两种情况下生成临时变量:
-
实参的类型正确,但不是左值。
-
实参的类型不正确,但可以转换为正确的类型。
左值是什么?左值参数是可被引用的数据对象,例如:变量、数组元素、结构成员、引用和解除引用的指针都是左值。
非左值包括字面常量(用引号括起的字符串除外,它们由其地址表示)和包含多项的表达式。
常规变量和const变量都可以视为左值,因为可通过地址访问它们,但常规变量属于可修改的左值,而cosnt变量属于不可修改的左值。
如:假设重新定义了refcube(),使其接受个常量引用参数:
double refcube(const double &ra)
{
return ra*ra*ra;
}
考虑如下代码:
double side = 3.0;
double * pd = &side;
double & rd = side;
long edgs = 5L;
double lens[4] = {2.0,5.0,10.0,12.0};
double c1 = refcube(side);
double c2 = refcube(lens[2]);
double c3 = refcube(rd);
doubele c4 = refcube(*pd);
double c5 = refcube(edge);//ra临时变量
double c6 = refcube(7.0);//ra临时变量
double c7 = refcube(side + 10.0);//ra临时变量
- 参数
side、lens[2]、rd和*pd
都是有名称的、double类型的数据对象,因此可以创建引用,而不需临时变量。 - edge虽然是变量。类型不匹配,double引用不能指向long。
- 另一方面,参数7.0和
side+10.0
的类型都正确,但没有名称,在这时编译器生成临时匿名变量,并让ra指向它。这些临时变量只在函数调用期间存在,此后编译器可以随便删除。
对于常量引用,这种行为是可行的,其他情况却不行呢?
例:
void swapr (int & a,int & b)
{
int temp;
temp=a;
a=b;
b=temp;
}
如果在早期C++较宽松规则下,执行下面的操作会发生什么?
long a =3,b=5;
swapr(a,b);
这里类型不匹配,因此编译器将创建两个临时int变量,将它们初始化为3和5,然后交换临时变量的内容,而a和b保持不变。
-
接受引用参数的函数的意图是修改作为传递的变量,则创建临时变量将阻止这种意图的实现。解决方法:禁止创建临时变量,现在的C++标准正是这样的(然而,在默认情况下,有些编译器将发出警告,而不是错误消息,因此看到有关临时变量的警告,不要忽略)。
-
refcube()函数,该函数的目的只是使用传递的值,而不是修改它们,因此临时变量不会造成任何不利的影响,反而使函数在可处理的参数种类方面更通用。因此,如果声明将引用指定为const,C++将在必要时生成临时变量。
-
实际上,对于形参为const引用的C++函数,如果实参不匹配,则其行为类似按值传递,为确保原始数据不被修改,将使用临时变量来存储值。
注:如果函数调用的参数不是左值或与相应的cosnt引用参数的类型不匹配,则C++将创建类型正确的匿名变量,将函数调用的参数的值传递给该匿名变量,并让参数来引用该变量。
14. 应尽可能使用cons
将引用参数声明为常量数据的引用的理由有三个:
-
使用const可以避免无意中修改数据的编程错误;
-
使用const使函数处理const和非const实参,否则将只能接受非const数据;
-
使用const引用使函数能够正确生成并使用临时变量。
c++新增了另一种引用:右值引用。这种引用可指向右值,是使用&&声明的:
double && rref = sqrt(36.00);
double j = 15.0;
double && jref = 2.0 * j+18.5;
cout<<rref<<'\n';
cout<<jref<<'\n';
目的为了让库设计人员能够提供有些操作的更有效的实现。
15. 何时使用引用参数
使用引用参数的主要原因有两个:
-
程序员能够修改调用函数中的数据对象。
- 通过传递引用而不是整个数据对象,可以提高程序的运行速度。
- 当数据对象较大时(如结构和类对象),第二个原因最重要。
这些也是使用指针参数的原因。这是有道理的,因为引用参数实际上是基于指针的代码的另一 个接口。那么,什么时候应使用引用、什么时候应使用指针呢?什么时候应按值传递呢?下面是一 些指导原则:
对于使用传递的值而不是修改的函数:
-
如果数据对象很小,如内置数据类型或小型结构,则按值传递。
-
如果数据对象是数组,则使用指针,因为这是唯一 的选择,并将指针声明为指向const的指针。
-
如果数据对象是较大的结构,则使用const指针或const引用,以提高程序的效率。这样可以节省复制结构所需的时间和空间。
-
如果数据对象是类对象,则使用const引用。类设计的语义常常要求使用引用,这是C++新增这项特性的主要原因。因此,传递类对象参数的标准方式是按引用传递。
对于修改调函数中数据的函数:
-
如果数据对象是内置数据类型,则使用指针。如果看到诸如fixit (&x)这样的代码(其中x是int),则很明显,该函数将修改x。
-
如果数据对象是数组,则只能使用指针。
-
如果数据对象是结构,则使用引用或指针。
-
如果数据对象是类对象,则使用引用。
当然,这只是一 些指导原则,很可能有充分的理由做出其他的选择。例如,对于基本类型,cin 使用引用。因此可以使用cin>>n
,而不是cin>>&n
。