1、面向对象的C++
c++是在C语言的基础上发展起来的一门语言,C++是即支持结构化程序编程又支持面向对象程序设计的混合型语言。他一方面提供了对C的兼容性,保持了C的简介、高效,接近汇编语言的特点,另一方面,C++引入了类、对象的概念,可以进行类的继承和派生,使C++成为一种面向对象的程序设计语言。早期的具有面向对象性能的程序语言存在很多缺点,如建立对象不凡便,与用户交互能力差等。C++克服了这些缺点,实现了真正的可视化编程。用户使用C++时,不用自己一一建立对象,只要在C++提供的框架内添加实现某种功能的代码即可。
2、C++对C语言的改进
c++与C语言兼容,C语言中的数据类型、运算符、表达式、函数定义和调用、预处理命令等在C++中都是适用的,还包括语句格式等。C++继承了C的风格和特点,但同时又对C的不足和问题做出了改进,主要包括:
(1)增加了一些新的运算符,使得C++应用起来更加方便,如::,new,delete,.*,->等。
(2)改进了类型系统,增加了安全性。C语言中类型转换很不严格,而C++规定类型转换大多采用强制转换,函数的说明必须使用原型,还对默认类型做了限制。
(3)增加了“引用”概念,是的引用函数参数更加方便。
(4)允许函数重载,允许设置默认参数,这些措施提高了编程的灵活性,还减少了冗余性。
(5)引进了内联函数的该概念,提高了程序的效率。
(6)对变量说明更加灵活,在满足先定义后使用的前提下,局部变量的定义和声明可以在程序块的任何位置。
3、C++的应用场景
C++并非万能药,这里举出一些C++的适用时机。
- C++适合构造程序中需求较稳定的部分,需求变化较大的部分可使用脚本语言;
- 程序须尽量发挥硬件的最高性能,且性能瓶颈在于CPU和内存;
- 程序须频繁地与操作系统或硬件沟通;
- 程序必须使用C++框架/库,如大部分游戏引擎(如Unreal/Source)及中间件(如Havok/FMOD),虽然有些C++库提供其他语言的绑定,但通常原生的API性能最好、最新;
- 项目中某个目标平台只提供C++编译器的支持。
按应用领域来说,C++适用于开发服务器软件、桌面应用、游戏、实时系统、高性
4、使用Visual Studio创建一个win32控制台应用程序
用Visual Studio不能单独编译一个.cpp或者一个.c文件,这些文件必须依赖于某一个项目,因此必须创建一个新项目,下面创建一个控制他应用程序。
点击确认后,即进入了如下界面
再输入程序如下:
1
2
3
4
5
6
7
8
9
|
#include "stdafx.h"
#include "iostream"
using
namespace
std;
int
main()
{
cout <<
"hello world!\n"
;
return
0;
}
|
#include<iostream>为预处理命令,预处理器包含在编译器中。iostream为C++自带的库文件,它包含标准流cin、cout输入和输出,当程序中需要用到这些输入输出流对象时,要用#include将其包含在程序中。
第二行using namespace std;,该语句是说明程序使用C++标准库的命名空间std。命名空间是ANSI C++引入的可以由用户命名的作用域,用来处理程序中常见的同名冲突。这个再后面会进行讲解。
运行程序,可以得到如下结果:
·运行结果如下:
5、C++对C的扩充
1、C++的输入输出
C++本身没有专门的输入输出语句,C++的输出和输入不是C++本身定义的,而是编译系统提供的I/O库中定义的,是用“流”的方式实现的,使用的是iostream库。
(1)输出流cout
1
|
cout<<表达式1[<<表达式2<<..<<表达式n];
|
该语句功能是:依次输出表达式1、表达式2、...表达式n的值。具体输出内容可以是一个整数、实数、字符及字符串。虽然cout不是C++本身提供的语句,但为了方便,常常由cout和流插入运算符<<实现输出的语句称为输出语句或cout语句。下面是一个实例:
1
2
3
4
5
6
7
8
|
#include "stdafx.h"
#include "iostream"
using
namespace
std;
int
main()
{
cout <<
"this is a c++ program"
<<endl;
}
|
在执行该语句是,系统先把插入的数据顺序存放在输出缓冲中,直到输出缓冲区满或遇到cout语句中的endl(或'\n',ends,flush)为止。将缓冲去中已有的数据一起输出,并清空缓冲区。
endl表示输出一个换行字符,同时刷新流,如果不用endl,还可以使用转移字符‘\n'来表示换行。
其中使用cout语句需要注意以下几点:
- 一个插入运算符<<只能插入一个输出项,多个输出项时要有多个插入运算符<<,例如,要输出变量a、b、c,不能写成cout<<a,b,c。而应写成cout<<a<<b<<c。
- cout输出时,用户不必通知计算机以何种类型输出,系统会自动判别输出数据的类型,使输出的数据按相应的类型输出。即使定义变量a、b、c时是不同类型的,但输出是可以直接写如下语句:cout<<a<<' '<<b<<endl
- 一条语句包含多个输出项时,可以分成若干行书写,也可以用多条语句输出。
例如:cout<<"this is a C++ program"<<endl可以写成:
1
2
3
4
|
cout <<
"this "
<<
"a C++"
<<
"program"
<< endl;
|
或者:
1
2
3
4
|
cout <<
"this "
;
cout <<
"a C++"
;
cout <<
"program"
;
cout << endl;
|
(2)、输入流cin
cin语句一般格式
1
|
cin>>变量>>[变量>>...>>变量n];
|
该语句功能为:运行程序时从键盘输入变量1、变量2、...变量n的值。
使用该语句需要注意以下几点:
- 一个提取运算符>>只能插入一个输入项,如果有多个输入项,要用多个提取运算符>>
运行程序是,从键盘上输入多个变量,多个值之间用空格、Tab或回车键分开。
- cin与cout类似,系统也会根据变量的类型从输入流中提取相应长度的字节。
例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
// example1.cpp: 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "iostream"
using
namespace
std;
int
main()
{
char
c1, c2;
int
a;
float
b;
cin >> c1 >> c2 >> a >> b;
}
|
需要注意的是不能用cin语句把空格字符和回车换行符作为字符输入给字符变量,他们将被跳过。如果想将空格字符或者回车换行符输入给字符变量,可以使用getchar()函数。
- 与cout类似,一个cin语句可以分写成若干行。
(3)、格式控制
利用格式控制符可以进行格式化的输入和输出。用oct、dec、hex分别将输入或输出的数值换成8进制、10进制及16进制。例如:
1
2
3
|
cout << oct << a << endl;
//输出a的8进制
cout << dec << a << endl;
//输出a的10进制
cout << hex << a << endl;
//输出a的16进制
|
此外,还有很多格式控制符,例如:
ws:输入流的时候删掉空白字符。
ends:输出一个null字符。
endl:输出一个换行字符,同时刷新流。
flush:刷新流。
下面通过一个实例加深了解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
// example1.cpp: 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "iostream"
using
namespace
std;
int
main()
{
char
a[20];
cin >> a;
cout << a << endl;
return
0;
}
|
这里发现,输入aaa bbb输出却只为aaa,这是因为遇见空格后就结束了,后面BB无法读取出来,所以输出的是aaa.
2、变量的存储类型
1、变量的作用域和生存期
变量的作用与即变量的作用范围。有的变量可以在整个程序或其他程序中使用,有的则只能在局部范围内使用。按作用域范围范围可以将变量分为两种:局部变量和全局变量。
变量的生存期是指变量从生成到被撤销的这段时间。实际上就是变量占用内存的时间。按生存期长短可将变量分为两种:动态变量和静态变量。
变量只能在其生存期里被引用,变量的作用域直接影响变量的生存期。作用域和生存期是从空间和时间的两个不同的角度来描述变量的特性。
- 局部变量的作用域和生存期
在一个函数内部定义的变量就是局部变量,其作用域只在本函数范围内有效,也就是说只有在本函数内才能使用他们,在此函数之外是不能使用这些变量的,这是因为函数内的变量是保存在栈内的,而所有栈内的内容在函数调用结束后会被清除。所以,局部变量的生存期是从函数被调用的时刻开始到函数返回调用处的时刻(静态变量除外)结束。在使用局部变量时,需要注意以下几点:
- 主函数main()中定义的变量也是局部变量,它只能在主函数中使用,其他函数不能使用。同时,主函数中也不能使用其他函数中定义的局部变量。
- 形参变量属于被调用函数的局部变量;实参则属于全局变量或调用函数的局部变量。
- 允许在不同的函数中使用相同的变量名,他们代表不同的对象,分配不同的单元,互不干扰,也不会发生混淆。
- 在复合语句中定义的变量也是局部变量,其作用域只在符合语句范围内。其生存周期是从复合语句被执行的时刻到复合语句执行完毕的时刻。
- 在函数声明中出现的参数名,其作用范围只在本行的括号内。实际上,编译系统对函数中声明的变量是忽略的,即使在调用函数时也没有为它们分配存储内存。例如:
int max(int a, int b);//函数声明a、b int max(int x, int y)//函数定义,形参是x、y { cout << x << y << endl;//合法,x、y在函数内有效 cout << a << b << endl;//非法,a、b在函数体中无效。 }
编译时,系统认为函数体中的a\b未经定义。
2.全局变量作用域和生存期
在函数外部做定义说明的变量,称为外部变量。它属于整个源程序文件。这是因为全局变量是保存在堆中的,堆内的数据可以从程序开始运行一直到程序运行结束。其作用域从定义变量的未知开始到源文件结束,或者是有extern说明的其他源文件。全局变量的生存期和程序相同。使用时需要注意以下几点:
- 应尽量少使用全局变量,因为全局变量在程序执行过程中始终占用内存单元,降低了函数的独立性、通用性、可靠性及可移植性,降低了程序的清晰性,容易出错。
- 若全局变量与局部变量同名,则全局变量被屏蔽。要引用全局变量,则必须在变量名前加上两个冒号::。
- 全局变量定义必须在所有的函数之外,且只能定义一次,并可赋初始值。全局变量定义的一般形式为:
1
|
[
extern
] 类型说明符全局变量名1[ =初始值1],...,全局变量名n[ =初始值n];
|
- 对全局变量进行声明,可扩展全局变量的作用域。全局变量说明的一般形式为:
extern 类型说明符 全局变量名1,...,全局变量名n;
2、变量的存储类型
在C++中变量除了有数据类型的属性之外,还有存储类别的属性。存储类别指的是数据在内存中的存储方法。存储方法分为静态存储和动态存储两大类。具体包含四种:自动(auto)、静态的(static)、寄存器的(register)和外部的(extern)。
考虑了变量的存储类型后,变量定义的完整形式应为:
1
2
3
4
5
6
|
存储类型说明符 数据类型说明符 变量名1,变量名2,...变量名n;
例如:
auto
char
c1,c2;
register
i;
static
int
a,b;
extern
int
x,y;
|
- 自动变量
程序中大多数变量属于自动变量。函数中的局部变量,如果不用关键字static加以声明,编译系统对它们是动态的分配存储空间的。函数的形参和在函数中定义的变量(包括在符合语句中定义的变量)都属于此类。在调用该函数时,系统给形参和函数中定义的变量分配存储空间,数据存储在动态存储区中,在函数调用结束后自动释放这些空间。如果是在复合语句中定义的变量,则在变量定义时分配存储空间,在符合语句结束时自动释放空间。如果在符合语句中定义的变量,则在变量定义时分配存储空间,在复合语句结束时自动释放空间。因此者类局部变量称为自动变量。自动变量用关键字auto作存储类别的声明。
例:
1
2
3
4
|
int
f(
int
a)
//定义f函数,a为形参
{
auto
int
b, c = 3;
//定义b和c为整型的自动变量
}
|
存储类型auto与int的顺序是任意的,而且关键字auto还可以省略,如果不写auto,则系统默认为自动存储模式,它属于动态存储方式。
注意,用auto、register、static声明变量时,是在定义的基础上加上这些关键字,而布恩那个单独使用。
2.静态变量
静态变量在整个程序生命周期内,其地址静止不变。
静态变量的类型说明符是static。静态变量属于静态存储类型,但静态存储类型的变量不一定是静态变量。例如,外部变量虽属于静态存储类型,但不一定是静态变量,必须用static加以定义后才能称为静态外部变量。
全局变量改变为静态变量后会改变它的作用域,限制了它的使用范围。当一个源程序由多个源文件组成时,非静态的全局变量可通过外部变量说明使其在多个文件中都有效。而静态全局变量只在定义该变量的源文件内有效,在同一项目的其他源文件中不能使用。
自动变量可以用static改变为静态自动变量,改变后,其生存周期为整个源程序,但是作用域与自动变量相同。此外需要注意的是,静态局部变量赋字操作只运行一次,此后再调用,不再进行赋值。
例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
#include "stdafx.h"
#include "iostream"
using
namespace
std;
int
main()
{
int
i;
void
func();
//函数说明
for
(i = 1; i <= 5; i++)
func();
//函数调用
return
0;
}
void
func()
//函数定义
{
static
int
j = 1;
//静态局部变量,其只运行一次。
++j;
cout << j <<
""
;
}
|
可以看到,五次调用函数func,但是赋值给j=1的操作只执行了一次。
3.寄存器变量(register型变量)
一般情况下,变量的值是存放再内存中的,当程序中用到哪一个变量的值时,由控制器发出指令将内存中该变量的值送到CPU的运算器中,而寄存器变量存放在CPU的寄存器中,使用时,不需要访问内存,而是直接从寄存器中读写,这样可提高效率。
寄存器变量的说明符为register,属于动态存储类型。只有局部自动变量和形式参数才可以定义为寄存器变量。
4.外部变量
外部变量(即全局变量)是在函数的外部定义的,它的作用域为从变量的定义开始,到本程序文件的末尾。在此作用域内,本文件的各个函数都可以引用全局变量。编译时将全局变量分配到静态存储区。
如果外部变量不在文件的开头定义,其有效的作用范围只限于定义处到文件结束。如果在定义之前想引用该全局变量,则应该在引用之前用关键字extern对该变量做外部变量声明,表示该变量是一个在后面定义的全局变量。有了此声明,就可以从声明处起,合法的引用该全局变量,这种声明称为提前引用声明。如果程序由多个文件组成,在一个文件中定义的外部变量,在另一个文件中对该外部变量进行声明后,也可以合法的引用该外部变量。
用extern扩展全局变量的作用域,虽然给程序带来了方便,但会使程序的可读性变差,修改不便,使用时要慎重。
3、函数的默认参数
在C和C++中使用函数时,包括函数的声明、定义、调用三部分,都要遵守相应的规则。
1、函数的声明
函数声明就是把函数的名字、函数类型以及形参的个数、类型和顺序通知编译系统,以便在遇到函数调用时,核查调用形式是否与声明相符。
函数声明的一般形式:
1
2
3
|
函数类型 函数名(参数类型1 参数名1,参数类型2 参数名2,...);
函数类型 函数名(参数类型1,参数类型2..);
|
第二种声明是对第一种声明的简化,它省略了参数名,因为函数声明不涉及函数体,所以编译系统不关心参数是什么。
2、函数的定义
函数定义是指对函数功能的实现,包括指定函数名、函数类型、形参及其类型、函数体等,他是一个完整的、独立的函数单位。
函数定义的一般形式:
1
2
3
4
5
6
|
函数类型 函数名(形式参数表)
{
声明部分;
函数体主体;
return
返回值;
}
|
3、函数的调用
使用该函数,叫做函数调用,函数调用方式是:
1
|
函数名(实际参数表)
|
只要函数声明出现在函数调用之前,就可以把包含函数体的函数定义移到函数调用的后面。因此,在程序中调用函数由以下两种方式:
1
2
3
4
5
6
7
8
|
方式1:
函数声明;
函数调用;
函数定义;
方式2
函数定义;
函数调用;
|
例如之前的例子,还可以这样写:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#include "stdafx.h"
#include "iostream"
using
namespace
std;
void
func()
//函数定义
{
static
int
j = 1;
//静态局部变量,其只运行一次。
++j;
cout << j <<
""
;
}
int
main()
{
int
i;
for
(i = 1; i <= 5; i++)
func();
//函数调用
return
0;
}
|
4、函数的默认参数
C++允许给函数形参赋予默认值。所谓默认值就是在调用时,可以不必给出某些参数的值,编译器会自动把默认值传递给调用语句。对于函数的形参,可以给出默认值,也可以不提供默认值,还可以指对形参的一部分给出默认值。默认值在函数参数较多时是非常有用的。可以只传必需的值。
使用默认参数时,需要注意以下几点:
- 默认参数设置位置
参数的默认值可以在声明中或定义中设置,但只能在其中一处设置,不允许在两处同时设置。如果函数的定义在函数调用之后,则只能在函数声明中设置默认参数。因为此时如果在定义中设置,编译器不知道哪个参数设置了默认值。
- 带默认参数的函数调用
设置了默认值的参数,函数调用是可以不再给值,直接读取默认值,也可以不区默认值,重新赋值。
例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
#include "stdafx.h"
#include "iostream"
using
namespace
std;
int
add(
int
a,
int
b = 5);
//函数声明
int
main()
{
int
a = 1;
int
b = 2;
cout<<add(a, b) << endl;
//函数调用,第二个参数没有取默认值
cout << add(a) << endl;
//函数调用,第二个参数取默认值
return
0;
}
int
add(
int
x,
int
y)
//函数定义
{
int
z;
z = x + y;
return
z;
}
|
输出结果为:
- 默认参数的顺序规定
如果一个函数中有多个默认参数,则默认参数应从右到左逐渐定义。即当某个参数是默认参数,那么它后面的参数必须都是默认参数。例如:
1
2
3
|
int
add(
int
a,
int
b,
int
c=1);
//true
int
add(
int
a=1,
int
b=1,
int
c=1);
//true
int
add(
int
a=1,
int
b=1,
int
c);
//false
|
当调用函数时 ,传进去的实参个数必须大于或等于无默认值的形参的个数,匹配参数时是从左至右去匹配。例如,对三个参数都是默认参数的,正确的调用格式为:
1
2
3
|
add()
//三个参数都取默认值1,函数值为3
add(2,3)
//a=2,b=3,c取默认值1,函数值为6
add(3,4,5)
//a、b、c都不取默认值,结果为12
|
- 参数默认值的限定
在前面的例子中,参数默认值都是常量,实际上,默认值可以是全局变量,甚至是一个函数调用。
例如
1
2
3
|
int
m = 1;
//m为全局变量
int
fun(
int
i = m);
//正确,参数默认值为全局变量m
int
add(
int
x;
int
y = fun());
//正确,add函数的参数默认值为fun()函数值,而且,fun()函数调用使用的是参数默认值。
|
但默认值不能是局部变量,因为默认参数的函数调用是在编译时确定的。
4、函数的重载
函数编程过程中,经常会遇到这种情况,就是需要编写若干个函数,他们的功能相似,但是参数不同,可以统一给这些函数取一个相同的名字,但设置不同的参数,编译系统在函数调用时能够将各个函数区分开来。如果两个函数名字相同并且在相同的域中被声明,但是参数表不同,那么他们就是重载函数。
重载函数必须是参数类型或参数个数不同。使用重载函数需要注意:
- 重载函数都应在一个域中被声明,不同域中声明的同名函数不是重载函数。
- 只有函数的返回类型不同,参数相同的不是重载函数。因为函数调用时系统无法根据函数返回类型确定执行哪个函数,因此会在编译时认定为是重复定义。
- 不要把功能不同的函数放在一起重载。这样会破坏程序的可读性和可理解性。
- 如果有函数重载,同时有些函数的形参带默认值时,这样有可能引发歧义,编译系统无法确定调用哪个函数,因而产生错误。
函数重载要求编译器能够唯一的确定调用一个函数应执行哪个函数代码,即采用哪个函数实现。进行函数重载时,要求同名函数在参数个数上不同,或者参数类型上不同,否则,将无法进行重载。
例:编写两个重载求和函数,一个计算两个整数的和,一个计算两个浮点型数的和。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
#include "stdafx.h"
#include "iostream"
using
namespace
std;
int
add(
int
x,
int
y);
//函数声明
double
add(
double
a,
double
b);
int
main()
{
cout<<add(2, 3) << endl;
//函数调用,第二个参数没有取默认值
cout << add(2.2,3.3) << endl;
//函数调用,第二个参数取默认值
return
0;
}
int
add(
int
x,
int
y)
//函数定义
{
return
x + y;
}
double
add(
double
a,
double
b)
//函数定义
{
return
a + b;
}
|
5、内联函数
内联函数是C++引进的新概念,在C语言中没有。内联函数具有一般函数的特性,他与一般函数的不同之处只在于函数调用的处理。一般函数进行调用时,要将程序执行权转到被调用函数中,执行完被调用函数后才再次返回到调用它的函数中;而内联函数是在编译时直接将内联函数的函数体代码嵌入到调用函数中,所以内联函数被执行时,不涉及到流程的转出和返回,也不涉及到参数传递,提高了执行效率。
内联函数是在函数声明或函数定义是,在函数名前加一个inline。示例如下
1
2
3
4
|
inline
int
add(
int
x,
int
y)
//函数定义
{
return
x + y;
}
|
使用内联函数有以下注意事项:
- 如果一个函数被指定为inline函数,则它将在函数中每个调用点上被内联的展开,使用内联函数是一种以空间换时间的行为,所以函数内语句较长或包含复杂的控制语句,如循环语句、if语句或switch语句或递归时,不宜使用内联函数。
- 关键字inline必须与函数定义放在一起才能使函数称为内联,仅仅放在函数声明前起不到任何作用。
- 并不是所有加了inline的函数都是内联函数,inline对于编译器来说只是一个建议,编译器可以选择忽略该建议,自动进行优化。所以当inline中出现递归、循环或者过多代码时,编译器自动将其作为普通函数调用。
- 在C++类中,类体内的成员函数自动被当成内联函数,应用非常广。
- 当编写复杂的应用程序时,内联函数的定义要放在头文件中,如果其他文件要调用这些内联函数的时候,只要包含这个头文件就可以了。
6、引用和引用传递
1、引用的定义
引用是C++中提供的一个新概念,它与指针密切相关。引用是一个变量的别名,定义引用类型变量,实质上是给一个已定义的变量起一个别名,系统不会为引用类型变量分配内存空间,只是使引用类型变量和其相关联的变量使用同一个内存空间。
定义引用类型变量的一般格式为:
1
2
3
4
5
|
<数据类型> &<引用名>=<变量名>
//&不是取地址符,是引用的标识
或
<数据类型> &<引用名> (变量名)
|
例如:
1
2
|
int
a=3;
int
&ra = a;
|
这里,ra就是一个引用,他是变量a的别名。引用ra和变量a不仅值相同,地址也相同。对引用进行的计算,例如:ra=ra+2;实质上是a加上2,a的结果为5.
使用引用的注意事项如下:
- 引用必须初始化,因为它只是某个变量的别名,只能在定义引用的同时给它赋值。
- 除了初始化,引用不能再赋新值,即引用再其整个生命周期中是不能被改变的,只能依附于同一个变量。
- 不能建立数组的引用,因为数组名表示的是一组数据的起始地址,它自己不是一个真正的数据类型。
- 不能对引用再进行引用。
下面通过一个实例加深了解。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
#include "stdafx.h"
#include "iostream"
using
namespace
std;
int
main()
{
int
a;
int
&ra = a;
//将ra引用为a
cout <<
"a="
<< a << endl;
cout <<
"ra="
<< ra << endl;
cout <<
"address of a is :"
<< &a << endl;
cout <<
"address of ra is :"
<< &ra << endl;
int
b = 8;
ra = b;
cout <<
"a="
<< a << endl;
cout <<
"b="
<< b << endl;
cout <<
"ra="
<< ra << endl;
cout <<
"address of a is :"
<< &a << endl;
cout <<
"address of b is :"
<< &b << endl;
cout <<
"address of ra is :"
<< &ra << endl;
return
0;
}
|
运行结果:
2、引用传递
引用传递是指将引用作为函数参数来实现的函数参数的传递。
一般的,函数形参为一般变量,调用时实参与形参之间参数传递只能是从实参到形参,是单向的。从被调用函数的角度来说,参数的值只能传入,不能传出,也就是通常的值传递。当用指针作为函数参数,调用时将实参的地址初始化成形参的指针,则可以实现实参和形参的双向传递,即地址传递。
引用传递是指引用作为函数的形参,当调用函数是,对应的形参就是相应实参的别名。在调用函数内对形参的修改就是对实参的修改;在调用函数外对实参的修改,当进入被调用函数内时,相应的形参就是已经修改的实参,实现了参数的双向传递。
例:利用自定义函数交换两个变量的值,要求用引用作为函数形参。
下面程序中自定义函数的形参为引用。