==Part2/4============================
=============================
■□第9节:自由记忆体治理
=============================
Q33:"deletep"会删去"p"指标,还是它指到的资料,"*p"?
该指标指到的资料。
"delete"真正的意思是:「删去指标所指到的东西」(deletethethingpointed
toby)。同样的英文误用也发生在C语言的「『释放』指标所指向的记忆体」上
("free(p)"真正的意思是:"free_the_stuff_pointed_to_by(p)")。
========================================
Q34:我能"free()"掉由"new"配置到的、"delete"掉由"malloc()"配置到的
记忆体吗?
不行。
在同一个程式里,使用malloc/free及new/delete是完全合法、合理、安全的;
但free掉由new配置到的,或delete掉由malloc配置到的指标则是不合法、
不合理、该被痛骂一顿的。
========================================
Q35:为什麽该用"new"而不是老字号的malloc()?
建构子/解构子、型别安全性、可被覆盖(overridability)。
建构子/解构子:和"malloc(sizeof(Fred))"不同,"newFred()"还会去呼叫
Fred的建构子。同理,"deletep"会去呼叫"*p"的解构子。
型别安全性:malloc()会传回一个不具型别安全的"void*",而"newFred()"则
会传回正确型态的指标(一个"Fred*")。
可被覆盖:"new"是个可被物件类别覆盖的运算子,而"malloc"不是以「各个类别
」作为覆盖的基准。
========================================
Q36:为什麽C++不替"new"及"delete"搭配个"realloc()"?
避免你产生意外。
当realloc()要拷贝配置区时,它做的是「逐位元bitwise」的拷贝,这会弄坏大
部份的C++物件。不过C++的物件应该要能自我拷贝才对:用它们自己的拷贝建构
子或设定运算子。
========================================
Q37:我该怎样配置/释放阵列?
用new[]和delete[]:
Fred*p=newFred[100];
//...
delete[]p;
每当你在"new"运算式中用了"[...]",你就必须在"delete"陈述中使用"[]"。
^^^^
这语法是必要的,因为「指向单一元素的指标」与「指向一个阵列的指标」在语法上
并无法区分开来。
========================================
Q38:万一我忘了将"[]"用在"delete"由"newFred[n]"配置到的阵列,会发生
什麽事?
灾难。
这是程式者的--而不是编译器的--责任,去确保new[]与delete[]的正确配
对。若你弄错了,编译器不会产生任何编译期或执行期的错误讯息。堆积(heap)被
破坏是最可能的结局,或是更糟的,你的程式会当掉。
========================================
Q39:成员函数做"deletethis"的动作是合法的(并且是好的)吗?
只要你小心的话就没事。
我所谓的「小心」是:
1)你得100%确定"this"是由"new"配置来的(而非"new[]",亦非自订的
"new"版本,一定要是最原始的"new")。
2)你得100%确定该成员函数是此物件最後一个会呼叫到的。
3)做完自杀的动作("deletethis;")後,你不能再去碰"this"的物件了,包
括资料及运作行为在内。
4)做完自杀的动作("deletethis;")後,你不能再去碰"this"指标了。
换句话说,你不能查看它、将它与其他指标或是NULL相比较、印出其值、
对它转型、对它做任何事情。
很自然的,这项警告也适用於:当"this"是个指向基底类别的指标,而解构子不是
virtual的场合。
========================================
Q40:我该怎麽用new来配置多维阵列?
有很多方法,端视你对阵列大小的伸缩性之要求而定。极端一点的情形,假如你在编
译期就知道所有阵列的维度,你可以静态地配置(就像C一样):
classFred{/*...*/};
voidmanipulateArray()
{
Fredmatrix[10][20];
//使用matrix[i][j]...