?教学目的与要求:
了解动态内存分配和引用的含义 。
掌握 new和 delete的使用及引用的使用 。
教学内容提要:
1,动态内存分配
2,引用;
3,课堂练习;
教学重点,new和 delete的使用和引用的使用 。
教学难点,new 和 delete的使用和引用的使用 。
教学进度,P35-P44
教学过程:
第 6 讲 动态内存分配和引用动态内存分配 是指在程序运行期间根据实际需要随时申请内存,并在不需要时释放。
按所占内存分类静态存储区栈在程序运行开始前就分配的存储空间。
局部变量在栈中分配存储空间。
堆 也称为自由存储单元,动态内存分配就是在堆中进行的。
在 C++中进行动态内存分配时可使用运算符 new和运算符 delete,相应地我们把申请和释放内存的过程称作 创建和删除 。
【 6.1 动态内存分配 】
保持与 C语言的兼容性,保留了 C语言中在 alloc.h头文件中用于动态内存分配的两个库函数,malloc()( 与运算符 new功能类似)和 free()( 与运算符 delete功能类似)。
注使用格式,
new 类型名 //动态变量
new 类型名 ( 初值 )
new 类型名 [ 元素个数 ] //动态数组功能,
生成一个 (或一批 )所给类型的无名动态变量,返回所生成变量的一个指针值 (首地址 )。
关键字 new的作用 是从堆中为程序分配指定数据类型所需的内存单元。若分配成功,则返回其首地址;否则,返回一个空指针。 new返回的内存地址必须赋给指针。
【 6.1.1 new】
例,int *pi,*pj,a=10;
char *pc;
pi = new int;
*pi = a*a;
pc = new char('A');
pj = new int[10];
使用格式,
delete 指针 或 delete [ ] 指针功能,释放通过 new生成的动态变量 (或动态数组 ),
但指针变量仍存在。
【 6.1.2 delete】
例:
int *pi,*pj;
pi = new int;
pj = new int[10];
...
delete pi;
//释放动态变量 *pi,但指针变量 pi仍存在
delete []pj;
例 6.1 操作符 new和 delete的使用。
#include <iostream.h>
void main()
{
int *p; // 声明一个整型指针变量 p
p=new int; // 动态分配一个存放 int型数据的内存
// 空间,并将首地址赋给 p
*p=10;
cout<<*p;
delete p; // 释放指针变量 p指向的内存空间
}
从键盘输入 10个 int型数,而后按输入的相反顺序输出它们。要求使用 new运算符动态申请数据空间存放数据。
使程序执行后的输入输出界面为,
Input 10 integers:
1 2 3 4 5 6 7 8 9 10
---- The result ----
10 9 8 7 6 5 4 3 2 1
例 6.2
#include <iostream.h>
void main() {
int i,*a,*p;
a = new int[10];
cout<<"input 10 integers:"<<endl;
for(i=0; i<10; i++)
cin>>*(a+i); //也可用 a[i]
cout<<"---- The result ----"<<endl;
for(p=a+9; p>=a; p--)
cout<<*p<<" ";
cout<<endl;
delete [ ]a;
}
6.2.1 引用简介简单的说,引用是某个变量或对象的别名 。 建立引用时,必须用某个变量名或对象名来对它进行初始化,从而将该引用绑定在那一个变量或对象上 。
即是说,建立引用并不重新为其分配内存空间,引用只是另一变量或对象的别名,
任何对引用的使用与改变都是对该引用所绑定的那一变量或对象的使用与改变 。
【 6.2 引用 】
1,引用的建立建立引用的格式如下:
类型 & 引用名 = 变量名或对象名例如,
int a=2,b;
int & refa=a; //引用 refa是 int型变量 a的别名
int & refb=b; //引用 refb是 int型变量 b的别名
refb=55 ; // b与 refb的当前值都将是 55
refa+=2; // a与 refa都在原有值 2的基础上增加
// 了 2,即当前值都变成了 4
例,6.3
#include <iostream.h>
void main()
{
int i;
int &j=i;
i=30;
cout<<"i="<<i<<"j="<<j<<"\n";
j=80;
cout<<"i="<<i<<"j="<<j<<"\n";
cout<<"Address of i"<<&i<<"\n";
cout <<"Address of j"<<&j<<"\n";
}
2,引用和指针的区别引用和指针从说明到使用上都有些相似,但在概念上却 有着明显的不同 。 主要区别在以下几个方面 。
(1) 指针表示的是一个对象变量的地址,而 引用则表示一个对象变量的别名 。 因此在程序中表示其对象变量时,
前者要通过取内容运算符,*”,而后者可直接代表 。 例如:
int a; int *pa=&a; int &ra=a;
当要对 a 赋值 123时,下述三个语句是等价的:
a=123; *pa=123; ra=123;
(2) 指针是可变的,它可以指向变量 a,也可以指向变量 b,而 引用则只能在建立时一次确定 ( 固定绑定在某一个变量上 ),不可改变 。
例如:
int a,b=456; int *p=&a; int &ra=a;
以后再执行,p=&b;”是合法的,它使指针 p又改指变量
b。 但不能通过,ra=b;”的赋值或,int &ra=b;”的重新建立新的绑定关系来改变引用 ra。 前者的,ra=b;”的赋值只是将 b的值 ( 即 456) 赋给了与 ra绑定的变量 a以及引用 ra本身;而后者试图为引用 ra重新建立新的绑定关系则会导致出现一个编译错误 ( ra重定义,重复初始化 ) 。
(3) 由于 引用本身不是一个独立的变量 ( 它本身不具有独立的变量地址,使用的是与其绑定的那一变量的地址 ),
所以,不能出现引用的引用,不能出现元素为引用的数组,
也不能使用指向引用的指针 ( 注意,可以出现指针的指针,
可以出现元素为指针的数组,也可以说明对指针的引用,这都缘于指针是独立变量的缘故 ) 。
int &&ref; //ERR! 不能出现引用的引用
int &refa[10]; //ERR! 不能出现元素为引用的数组
int &*refp; //ERR! 不能使用指向引用的指针
int *pi,*&pref=pi; //OK! 可以说明对指针的引用
//将引用 pref与 int*类型的指针变量 pi进行了绑定
3,引用型参数以,<类型 >&” 形式说明的函数参数,可实现
,双向传值,( 被调函数中对形参值的使用与改变,
就是对主调函数中调用语句处所对应实参变量值的直接使用与改变 ) 。
可这样理解:引用型形参是调用语句处所对应实参变量的别名,而且系统又将该形参与实参进行了绑定 。
4,引用型的函数返回值函数非引用返回值时,要生成一个值的副本。而用引用返回值时,不生成值的副本。
例,6.4
#include <iostream.h>
float temp;
float fn1(float r)
{
temp=r*r*3.14;
return temp;
}
float &fn2(float r)
{
temp=r*r*3.14;
return temp;
}
void main()
{ float a=fn1(5.0);
float &b=fn1(5.0); //warning
float c=fn2(5.0);
float &d=fn2(5.0);
cout<<a<<’’<<b<<’’<<c<<’’<<d<<endl;
}
临时变量
5.0
78.5
fn2() r
c
main()
temp78.5
78.5
fn1() r
a
main()
temp
5.0
78.5
78.5
注意,引用返回值的函数的返回值必须是全局变量。
例 6.5 用引用返回函数的值。
#include<iostream.h>
int A[10];
int& array(int i);
void main()
{ int i,number;
A[0]=0;
A[1]=1;
cin>>number;
for (i=2;i<number;i++)
{ array(i)=array(i-2)+array(i-1);
cout<<"array("<<i<<")="<<array(i)<<endl;
}
}
int& array(int i)
{
return A[i];
}
1.
#include <iostream.h>
void main()
{
int a;
int &ra=a;
int *pa=&a;
cout<<"&a ="<<&a<<endl;
cout<<"&ra="<<&ra<<endl;
cout<<"&pa="<<&pa<<endl;
a=123;
cout<<"a="<<a<<endl;
cout<<"*pa="<<*pa<<endl;
cout<<"ra="<<ra<<endl;
课堂练习:
*pa=456;
cout<<"a="<<a<<endl;
cout<<"*pa="<<*pa<<endl;
cout<<"ra="<<ra<<endl;
ra=789;
cout<<"a="<<a<<endl;
cout<<"*pa="<<*pa<<endl;
cout<<"ra="<<ra<<endl;
}
程序执行后的显示结果如下,
&a =0x0065FDF4
&ra=0x0065FDF4
&pa=0x0065FDF0
a=123
*pa=123
ra=123
a=456
*pa=456
ra=456
a=789
*pa=789
ra=789
2、
#include <iostream.h>
int & maxr(int& m,int& n) {
if(m>n)
return m; //返回变量 ( 可作左值 )
return n;
}
void main()
{
int a=3,b=5,c=0;
cout<<"a,b,c = "<<a<<","<<b<<","<<c<<endl;
//输出,a,b,c = 3,5,0
c = maxr(a,b); //返回引用,即变量 b本身 ( 以及 b的值 )
cout<<"a,b,c = "<<a<<","<<b<<","<<c<<endl;
//输出,a,b,c = 3,5,5
maxr(a,b)=10; //返回引用,即变量 b本身,而后为 b重新赋值
cout<<"a,b,c = "<<a<<","<<b<<","<<c<<endl;
//输出,a,b,c = 3,10,5
maxr(a,b)++; //返回引用,即变量 b本身,而后实现 b值加 1
cout<<"a,b,c = "<<a<<","<<b<<","<<c<<endl;
//输出,a,b,c = 3,11,5
}
程序执行后的显示结果如下:
a,b,c = 3,5,0
a,b,c = 3,5,5
a,b,c = 3,10,5
a,b,c = 3,11,5
作业:
1、动态内存分配,new和 delete的使用
2,引用:引用的特征;
引用作为函数参数;
引用作为函数返回值;
小结
P47 2.14,2.16
了解动态内存分配和引用的含义 。
掌握 new和 delete的使用及引用的使用 。
教学内容提要:
1,动态内存分配
2,引用;
3,课堂练习;
教学重点,new和 delete的使用和引用的使用 。
教学难点,new 和 delete的使用和引用的使用 。
教学进度,P35-P44
教学过程:
第 6 讲 动态内存分配和引用动态内存分配 是指在程序运行期间根据实际需要随时申请内存,并在不需要时释放。
按所占内存分类静态存储区栈在程序运行开始前就分配的存储空间。
局部变量在栈中分配存储空间。
堆 也称为自由存储单元,动态内存分配就是在堆中进行的。
在 C++中进行动态内存分配时可使用运算符 new和运算符 delete,相应地我们把申请和释放内存的过程称作 创建和删除 。
【 6.1 动态内存分配 】
保持与 C语言的兼容性,保留了 C语言中在 alloc.h头文件中用于动态内存分配的两个库函数,malloc()( 与运算符 new功能类似)和 free()( 与运算符 delete功能类似)。
注使用格式,
new 类型名 //动态变量
new 类型名 ( 初值 )
new 类型名 [ 元素个数 ] //动态数组功能,
生成一个 (或一批 )所给类型的无名动态变量,返回所生成变量的一个指针值 (首地址 )。
关键字 new的作用 是从堆中为程序分配指定数据类型所需的内存单元。若分配成功,则返回其首地址;否则,返回一个空指针。 new返回的内存地址必须赋给指针。
【 6.1.1 new】
例,int *pi,*pj,a=10;
char *pc;
pi = new int;
*pi = a*a;
pc = new char('A');
pj = new int[10];
使用格式,
delete 指针 或 delete [ ] 指针功能,释放通过 new生成的动态变量 (或动态数组 ),
但指针变量仍存在。
【 6.1.2 delete】
例:
int *pi,*pj;
pi = new int;
pj = new int[10];
...
delete pi;
//释放动态变量 *pi,但指针变量 pi仍存在
delete []pj;
例 6.1 操作符 new和 delete的使用。
#include <iostream.h>
void main()
{
int *p; // 声明一个整型指针变量 p
p=new int; // 动态分配一个存放 int型数据的内存
// 空间,并将首地址赋给 p
*p=10;
cout<<*p;
delete p; // 释放指针变量 p指向的内存空间
}
从键盘输入 10个 int型数,而后按输入的相反顺序输出它们。要求使用 new运算符动态申请数据空间存放数据。
使程序执行后的输入输出界面为,
Input 10 integers:
1 2 3 4 5 6 7 8 9 10
---- The result ----
10 9 8 7 6 5 4 3 2 1
例 6.2
#include <iostream.h>
void main() {
int i,*a,*p;
a = new int[10];
cout<<"input 10 integers:"<<endl;
for(i=0; i<10; i++)
cin>>*(a+i); //也可用 a[i]
cout<<"---- The result ----"<<endl;
for(p=a+9; p>=a; p--)
cout<<*p<<" ";
cout<<endl;
delete [ ]a;
}
6.2.1 引用简介简单的说,引用是某个变量或对象的别名 。 建立引用时,必须用某个变量名或对象名来对它进行初始化,从而将该引用绑定在那一个变量或对象上 。
即是说,建立引用并不重新为其分配内存空间,引用只是另一变量或对象的别名,
任何对引用的使用与改变都是对该引用所绑定的那一变量或对象的使用与改变 。
【 6.2 引用 】
1,引用的建立建立引用的格式如下:
类型 & 引用名 = 变量名或对象名例如,
int a=2,b;
int & refa=a; //引用 refa是 int型变量 a的别名
int & refb=b; //引用 refb是 int型变量 b的别名
refb=55 ; // b与 refb的当前值都将是 55
refa+=2; // a与 refa都在原有值 2的基础上增加
// 了 2,即当前值都变成了 4
例,6.3
#include <iostream.h>
void main()
{
int i;
int &j=i;
i=30;
cout<<"i="<<i<<"j="<<j<<"\n";
j=80;
cout<<"i="<<i<<"j="<<j<<"\n";
cout<<"Address of i"<<&i<<"\n";
cout <<"Address of j"<<&j<<"\n";
}
2,引用和指针的区别引用和指针从说明到使用上都有些相似,但在概念上却 有着明显的不同 。 主要区别在以下几个方面 。
(1) 指针表示的是一个对象变量的地址,而 引用则表示一个对象变量的别名 。 因此在程序中表示其对象变量时,
前者要通过取内容运算符,*”,而后者可直接代表 。 例如:
int a; int *pa=&a; int &ra=a;
当要对 a 赋值 123时,下述三个语句是等价的:
a=123; *pa=123; ra=123;
(2) 指针是可变的,它可以指向变量 a,也可以指向变量 b,而 引用则只能在建立时一次确定 ( 固定绑定在某一个变量上 ),不可改变 。
例如:
int a,b=456; int *p=&a; int &ra=a;
以后再执行,p=&b;”是合法的,它使指针 p又改指变量
b。 但不能通过,ra=b;”的赋值或,int &ra=b;”的重新建立新的绑定关系来改变引用 ra。 前者的,ra=b;”的赋值只是将 b的值 ( 即 456) 赋给了与 ra绑定的变量 a以及引用 ra本身;而后者试图为引用 ra重新建立新的绑定关系则会导致出现一个编译错误 ( ra重定义,重复初始化 ) 。
(3) 由于 引用本身不是一个独立的变量 ( 它本身不具有独立的变量地址,使用的是与其绑定的那一变量的地址 ),
所以,不能出现引用的引用,不能出现元素为引用的数组,
也不能使用指向引用的指针 ( 注意,可以出现指针的指针,
可以出现元素为指针的数组,也可以说明对指针的引用,这都缘于指针是独立变量的缘故 ) 。
int &&ref; //ERR! 不能出现引用的引用
int &refa[10]; //ERR! 不能出现元素为引用的数组
int &*refp; //ERR! 不能使用指向引用的指针
int *pi,*&pref=pi; //OK! 可以说明对指针的引用
//将引用 pref与 int*类型的指针变量 pi进行了绑定
3,引用型参数以,<类型 >&” 形式说明的函数参数,可实现
,双向传值,( 被调函数中对形参值的使用与改变,
就是对主调函数中调用语句处所对应实参变量值的直接使用与改变 ) 。
可这样理解:引用型形参是调用语句处所对应实参变量的别名,而且系统又将该形参与实参进行了绑定 。
4,引用型的函数返回值函数非引用返回值时,要生成一个值的副本。而用引用返回值时,不生成值的副本。
例,6.4
#include <iostream.h>
float temp;
float fn1(float r)
{
temp=r*r*3.14;
return temp;
}
float &fn2(float r)
{
temp=r*r*3.14;
return temp;
}
void main()
{ float a=fn1(5.0);
float &b=fn1(5.0); //warning
float c=fn2(5.0);
float &d=fn2(5.0);
cout<<a<<’’<<b<<’’<<c<<’’<<d<<endl;
}
临时变量
5.0
78.5
fn2() r
c
main()
temp78.5
78.5
fn1() r
a
main()
temp
5.0
78.5
78.5
注意,引用返回值的函数的返回值必须是全局变量。
例 6.5 用引用返回函数的值。
#include<iostream.h>
int A[10];
int& array(int i);
void main()
{ int i,number;
A[0]=0;
A[1]=1;
cin>>number;
for (i=2;i<number;i++)
{ array(i)=array(i-2)+array(i-1);
cout<<"array("<<i<<")="<<array(i)<<endl;
}
}
int& array(int i)
{
return A[i];
}
1.
#include <iostream.h>
void main()
{
int a;
int &ra=a;
int *pa=&a;
cout<<"&a ="<<&a<<endl;
cout<<"&ra="<<&ra<<endl;
cout<<"&pa="<<&pa<<endl;
a=123;
cout<<"a="<<a<<endl;
cout<<"*pa="<<*pa<<endl;
cout<<"ra="<<ra<<endl;
课堂练习:
*pa=456;
cout<<"a="<<a<<endl;
cout<<"*pa="<<*pa<<endl;
cout<<"ra="<<ra<<endl;
ra=789;
cout<<"a="<<a<<endl;
cout<<"*pa="<<*pa<<endl;
cout<<"ra="<<ra<<endl;
}
程序执行后的显示结果如下,
&a =0x0065FDF4
&ra=0x0065FDF4
&pa=0x0065FDF0
a=123
*pa=123
ra=123
a=456
*pa=456
ra=456
a=789
*pa=789
ra=789
2、
#include <iostream.h>
int & maxr(int& m,int& n) {
if(m>n)
return m; //返回变量 ( 可作左值 )
return n;
}
void main()
{
int a=3,b=5,c=0;
cout<<"a,b,c = "<<a<<","<<b<<","<<c<<endl;
//输出,a,b,c = 3,5,0
c = maxr(a,b); //返回引用,即变量 b本身 ( 以及 b的值 )
cout<<"a,b,c = "<<a<<","<<b<<","<<c<<endl;
//输出,a,b,c = 3,5,5
maxr(a,b)=10; //返回引用,即变量 b本身,而后为 b重新赋值
cout<<"a,b,c = "<<a<<","<<b<<","<<c<<endl;
//输出,a,b,c = 3,10,5
maxr(a,b)++; //返回引用,即变量 b本身,而后实现 b值加 1
cout<<"a,b,c = "<<a<<","<<b<<","<<c<<endl;
//输出,a,b,c = 3,11,5
}
程序执行后的显示结果如下:
a,b,c = 3,5,0
a,b,c = 3,5,5
a,b,c = 3,10,5
a,b,c = 3,11,5
作业:
1、动态内存分配,new和 delete的使用
2,引用:引用的特征;
引用作为函数参数;
引用作为函数返回值;
小结
P47 2.14,2.16