首页
IT
登录
6mi
u
盘
搜
搜 索
IT
C++析构函数(Destructor)
C++析构函数(Destructor)
xiaoxiao
2021-04-13
24
创建对象时系统会自动调用构造函数进行初始化工作,同样,销毁对象时系统也会自动调用一个函数来进行清理工作,例如释放分配的内存、关闭打开的文件等,这个函数就是析构函数。
析构函数(Destructor)也是一种特殊的成员函数,没有返回值,不需要程序员显式调用(程序员也没法显式调用),而是在销毁对象时自动执行。
构造函数的名字和类名相同,而析构函数的名字是在类名前面加一个
~
符号。
注意:析构函数没有参数,不能被重载,因此一个类只能有一个析构函数。如果用户没有定义,编译器会自动生成一个默认的析构函数。
上节我们定义了一个 VLA 类来模拟变长数组,它使用一个构造函数为数组分配内存,这些内存在数组被销毁后不会自动释放,所以非常有必要再添加一个析构函数,专门用来释放已经分配的内存。请看下面的完整示例:
#include
<iostream>
using
namespace
std
;
class
VLA
{
public
:
VLA
(
int
len
);
//构造函数
~
VLA
();
//析构函数
public
:
void
input
();
//从控制台输入数组元素
void
show
();
//显示数组元素
private
:
int
*
at
(
int
i
);
//获取第i个元素的指针
private
:
const
int
m_len
;
//数组长度
int
*
m_arr
;
//数组指针
int
*
m_p
;
//指向数组第i个元素的指针
}
;
VLA
::
VLA
(
int
len
):
m_len
(
len
)
{
if
(
len
>
0
)
{
m_arr
=
new
int
[
len
];
/*分配内存*/
}
else
{
m_arr
=
NULL
;
}
}
VLA
::~
VLA
()
{
delete
[]
m_arr
;
//释放内存
}
void
VLA
::
input
()
{
for
(
int
i
=
0
;
m_p
=
at
(
i
);
i
++)
{
cin
>>*
at
(
i
);
}
}
void
VLA
::
show
()
{
for
(
int
i
=
0
;
m_p
=
at
(
i
);
i
++)
{
if
(
i
==
m_len
-
1
)
{
cout
<<*
at
(
i
)<<
endl
;
}
else
{
cout
<<*
at
(
i
)<<
", "
;
}
}
}
int
*
VLA
::
at
(
int
i
)
{
if
(!
m_arr
||
i
<
0
||
i
>=
m_len
)
{
return
NULL
;
}
else
{
return
m_arr
+
i
;
}
}
int
main
()
{
//创建一个有n个元素的数组(对象)
int
n
;
cout
<<
"Input array length: "
;
cin
>>
n
;
VLA
*
parr
=
new
VLA
(
n
);
//输入数组元素
cout
<<
"Input "
<<
n
<<
" numbers: "
;
parr
->
input
();
//输出数组元素
cout
<<
"Elements: "
;
parr
->
show
();
//删除数组(对象)
delete
parr
;
return
0
;
}
运行结果:
Input array length: 5
Input 5 numbers: 99 23 45 10 100
Elements: 99, 23, 45, 10, 100
~VLA()
就是 VLA 类的析构函数,它的唯一作用就是在删除对象(第 53 行代码)后释放已经分配的内存。
函数名是标识符的一种,原则上标识符的命名中不允许出现
~
符号,在析构函数的名字中出现的
~
可以认为是一种特殊情况,目的是为了和构造函数的名字加以对比和区分。
注意:at() 函数只在类的内部使用,所以将它声明为 private 属性;m_len 变量不允许修改,所以用 const 限制。
C++ 中的 new 和 delete 分别用来分配和释放内存,它们与C语言中 malloc()、free() 最大的一个不同之处在于:用 new 分配内存时会调用构造函数,用 delete 释放内存时会调用析构函数。构造函数和析构函数对于类来说是不可或缺的,所以在C++中我们非常鼓励使用 new 和 delete。
析构函数的执行时机
析构函数在对象被销毁时调用,而对象的销毁时机与它所在的内存区域有关。不了解内存分区的读者请阅读《
C语言和内存
》专题。
在所有函数之外创建的对象是全局对象,它和全局变量类似,位于内存分区中的全局数据区,程序在结束执行时会调用这些对象的析构函数。
在函数内部创建的对象是局部对象,它和局部变量类似,位于栈区,函数执行结束时会调用这些对象的析构函数。
new 创建的对象位于堆区,通过 delete 删除时才会调用析构函数;如果没有 delete,析构函数就不会被执行。
下面的例子演示了析构函数的执行。
#include
<iostream>
#include
<string>
using
namespace
std
;
class
Demo
{
public
:
Demo
(
string
s
);
~
Demo
();
private
:
string
m_s
;
}
;
Demo
::
Demo
(
string
s
):
m_s
(
s
)
{
}
Demo
::~
Demo
()
{
cout
<<
m_s
<<
endl
;
}
void
func
()
{
//局部对象
Demo
obj1
(
"1"
);
}
//全局对象
Demo
obj2
(
"2"
);
int
main
()
{
//局部对象
Demo
obj3
(
"3"
);
//new创建的对象
Demo
*
pobj4
=
new
Demo
(
"4"
);
func
();
cout
<<
"main"
<<
endl
;
return
0
;
}
运行结果:
1
main
3
2
转载请注明原文地址: https://ju.6miu.com/read-668617.html
技术
最新回复
(
0
)