📄 00000001.htm
字号:
<HTML><HEAD> <TITLE>BBS水木清华站∶精华区</TITLE></HEAD><BODY><CENTER><H1>BBS水木清华站∶精华区</H1></CENTER> <BR>== Part 2/4 ============================ <BR> <BR>comp.lang.c++ Frequently Asked Questions list (with answers, fortunately). <BR>Copyright (C) 1991-96 Marshall P. Cline, Ph.D. <BR>Posting 2 of 4. <BR>Posting #1 explains copying permissions, (no)warranty, table-of-contents, etc <BR> <BR>============================= <BR>■□ 第9节:自由记忆体管理 <BR>============================= <BR> <BR>Q33:"delete p" 会删去 "p" 指标,还是它指到的资料,"*p" ? <BR> <BR>该指标指到的资料。 <BR> <BR>"delete" 真正的意思是:「删去指标所指到的东西」(delete the thing pointed <BR>to by)。同样的英文误用也发生在 C 语言的「『释放』指标所指向的记忆体」上 <BR>("free(p)" 真正的意思是:"free_the_stuff_pointed_to_by(p)" )。 <BR> <BR>======================================== <BR> <BR>Q34:我能 "free()" 掉由 "new" 配置到的、"delete" 掉由 "malloc()" 配置到的 <BR> 记忆体吗? <BR> <BR>不行。 <BR> <BR>在同一个程式里,使用 malloc/free 及 new/delete 是完全合法、合理、安全的; <BR>但 free 掉由 new 配置到的,或 delete 掉由 malloc 配置到的指标则是不合法、 <BR>不合理、该被痛骂一顿的。 <BR> <BR>======================================== <BR> <BR>Q35:为什麽该用 "new" 而不是老字号的 malloc() ? <BR> <BR>建构子/解构子、型别安全性、可被覆盖(overridability)。 <BR> <BR>建构子/解构子:和 "malloc(sizeof(Fred))" 不同,"new Fred()" 还会去呼叫 <BR>Fred 的建构子。同理,"delete p" 会去呼叫 "*p" 的解构子。 <BR> <BR>型别安全性:malloc() 会传回一个不具型别安全的 "void*",而 "new Fred()" 则 <BR>会传回正确型态的指标(一个 "Fred*")。 <BR> <BR>可被覆盖:"new" 是个可被物件类别覆盖的运算子,而 "malloc" 不是以「各个类别 <BR>」作为覆盖的基准。 <BR> <BR>======================================== <BR> <BR>Q36:为什麽 C++ 不替 "new" 及 "delete" 搭配个 "realloc()" ? <BR> <BR>避免你产生意外。 <BR> <BR>当 realloc() 要拷贝配置区时,它做的是「逐位元 bitwise」的拷贝,这会弄坏大 <BR>部份的 C++ 物件。不过 C++ 的物件应该要能自我拷贝才对:用它们自己的拷贝建构 <BR>子或设定运算子。 <BR> <BR>======================================== <BR> <BR>Q37:我该怎样配置/释放阵列? <BR> <BR>用 new[] 和 delete[] : <BR> <BR> Fred* p = new Fred[100]; <BR> //... <BR> delete [] p; <BR> <BR>每当你在 "new" 运算式中用了 "[...]",你就必须在 "delete" 陈述中使用 "[]"。 <BR> ^^^^ <BR>这语法是必要的,因为「指向单一元素的指标」与「指向一个阵列的指标」在语法上 <BR>并无法区分开来。 <BR> <BR>======================================== <BR> <BR>Q38:万一我忘了将 "[]" 用在 "delete" 由 "new Fred[n]" 配置到的阵列,会发生 <BR> 什麽事? <BR> <BR>灾难。 <BR> <BR>这是程式者的--而不是编译器的--责任,去确保 new[] 与 delete[] 的正确配 <BR>对。若你弄错了,编译器不会产生任何编译期或执行期的错误讯息。堆积(heap)被 <BR>破坏是最可能的结局,或是更糟的,你的程式会当掉。 <BR> <BR>======================================== <BR> <BR>Q39:成员函数做 "delete this" 的动作是合法的(并且是好的)吗? <BR> <BR>只要你小心的话就没事。 <BR> <BR>我所谓的「小心」是: <BR> <BR> 1) 你得 100% 确定 "this" 是由 "new" 配置来的(而非 "new[]",亦非自订的 <BR> "new" 版本,一定要是最原始的 "new")。 <BR> <BR> 2) 你得 100% 确定该成员函数是此物件最後一个会呼叫到的。 <BR> <BR> 3) 做完自杀的动作 ("delete this;") 後,你不能再去碰 "this" 的物件了,包 <BR> 括资料及运作行为在内。 <BR> <BR> 4) 做完自杀的动作 ("delete this;") 後,你不能再去碰 "this" 指标了。 <BR> 换句话说,你不能查看它、将它与其他指标或是 NULL 相比较、印出其值、 <BR> 对它转型、对它做任何事情。 <BR> <BR>很自然的,这项警告也适用於:当 "this" 是个指向基底类别的指标,而解构子不是 <BR>virtual 的场合。 <BR> <BR>======================================== <BR> <BR>Q40:我该怎麽用 new 来配置多维阵列? <BR> <BR>有很多方法,端视你对阵列大小的伸缩性之要求而定。极端一点的情形,如果你在编 <BR>译期就知道所有阵列的维度,你可以静态地配置(就像 C 一样): <BR> <BR> class Fred { /*...*/ }; <BR> <BR> void manipulateArray() <BR> { <BR> Fred matrix[10][20]; <BR> <BR> //使用 matrix[i][j]... <BR> <BR> //不须特地去释放该阵列 <BR> } <BR> <BR>另一个极端情况,如果你希望该矩阵的每个小块都能不一样大,你可以在自由记忆体 <BR>里配置之: <BR> <BR> void manipulateArray(unsigned nrows, unsigned ncols[]) <BR> //'nrows' 是该阵列之列数。 <BR> //所以合法的列数为 (0, nrows-1) 开区间。 <BR> //'ncols[r]' 则是 'r' 列的行数 ('r' 值域为 [0..nrows-1])。 <BR> { <BR> Fred** matrix = new Fred*[nrows]; <BR> for (unsigned r = 0; r < nrows; ++r) <BR> matrix[r] = new Fred[ ncols[r] ]; <BR> <BR> //使用 matrix[i][j]... <BR> <BR> //释放就是配置的反动作: <BR> for (r = nrows; r > 0; --r) <BR> delete [] matrix[r-1]; <BR> delete [] matrix; <BR> } <BR> <BR>======================================== <BR> <BR>Q41:C++ 能不能做到在执行时期才指定阵列的长度? <BR> <BR>可以。STL 有一个 vector template 提供这种行为。请参考“程式库”一节的 STL <BR>项目。 <BR> <BR>不行。内建的阵列型态必须在编译期就指定它的长度了。 <BR> <BR>可以,内建的阵列可以在执行期才指定第一个索引的□围。譬如说,和上一则 FAQ <BR>相较,如果你只需要第一个维度大小能够变动,你可以 new 一个阵列的阵列(而不 <BR>是阵列指标的阵列 "an array of pointers to arrays"): <BR> <BR> const unsigned ncols = 100; <BR> //'ncols' 不是执行期才决定的变数 (用来代表阵列的行数) <BR> <BR> class Fred { ... }; <BR> <BR> void manipulateArray(unsigned nrows) <BR> //'nrows' 是执行期才决定的变数 (用来代表阵列的列数) <BR> { <BR> Fred (*matrix)[ncols] = new Fred[nrows][ncols]; <BR> <BR> //用 matrix[i][j] 来处理 <BR> <BR> //deletion 是物件配置的逆运算: <BR> delete [] matrix; <BR> } <BR> <BR>如果你不光是需要在执行期改变阵列的第一个维度的话,就不能这样做了。 <BR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -