龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > 软件开发 > C/C++开发 >

C++语言常见问题解答(2)

时间:2009-12-22 15:42来源:未知 作者:admin 点击:
分享到:
== Part 2/4 ============================ ============================= ■□ 第9节:自由记忆体治理 ============================= Q33:"delete p" 会删去

   == Part 2/4  ============================ 

============================= 

  

■□ 第9节:自由记忆体治理 

  

============================= 

  

 

  

Q33:"delete p" 会删去 "p" 指标,还是它指到的资料,"*p" ? 

  

 

  

该指标指到的资料。 

  

 

  

"delete" 真正的意思是:「删去指标所指到的东西」(delete the thing pointed 

  

to by)。同样的英文误用也发生在 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))" 不同,"new Fred()" 还会去呼叫 

  

Fred 的建构子。同理,"delete p" 会去呼叫 "*p" 的解构子。 

  

 

  

型别安全性:malloc() 会传回一个不具型别安全的 "void*",而 "new Fred()" 则 

  

会传回正确型态的指标(一个 "Fred*")。 

  

 

  

可被覆盖:"new" 是个可被物件类别覆盖的运算子,而 "malloc" 不是以「各个类别 

  

」作为覆盖的基准。 

  

 

  

======================================== 

  

 

  

Q36:为什麽 C++ 不替 "new" 及 "delete" 搭配个 "realloc()" ? 

  

 

  

避免你产生意外。 

  

 

  

当 realloc() 要拷贝配置区时,它做的是「逐位元 bitwise」的拷贝,这会弄坏大 

  

  

部份的 C++ 物件。不过 C++ 的物件应该要能自我拷贝才对:用它们自己的拷贝建构 

  

子或设定运算子。 

  

 

  

======================================== 

  

 

  

Q37:我该怎样配置/释放阵列? 

  

 

  

用 new[] 和 delete[] : 

  

 

  

   Fred* p = new Fred[100]; 

  

   //... 

  

   delete [] p; 

  

 

  

每当你在 "new" 运算式中用了 "[...]",你就必须在 "delete" 陈述中使用 "[]"。 

  

        ^^^^ 

  

这语法是必要的,因为「指向单一元素的指标」与「指向一个阵列的指标」在语法上 

  

并无法区分开来。 

  

 

  

======================================== 

  

 

  

Q38:万一我忘了将 "[]" 用在 "delete" 由 "new Fred[n]" 配置到的阵列,会发生 

  

    什麽事? 

  

 

  

灾难。 

  

 

  

这是程式者的--而不是编译器的--责任,去确保 new[] 与 delete[] 的正确配 

  

对。若你弄错了,编译器不会产生任何编译期或执行期的错误讯息。堆积(heap)被 

  

破坏是最可能的结局,或是更糟的,你的程式会当掉。 

  

 

  

======================================== 

  

 

  

Q39:成员函数做 "delete this" 的动作是合法的(并且是好的)吗? 

  

 

  

只要你小心的话就没事。 

  

 

  

我所谓的「小心」是: 

  

 

  

   1) 你得 100% 确定 "this" 是由 "new" 配置来的(而非 "new[]",亦非自订的 

  

   

"new" 版本,一定要是最原始的 "new")。 

  

 

  

   2) 你得 100% 确定该成员函数是此物件最後一个会呼叫到的。 

  

 

  

   3) 做完自杀的动作 ("delete this;") 後,你不能再去碰 "this" 的物件了,包 

  

    括资料及运作行为在内。 

  

 

  

   4) 做完自杀的动作 ("delete this;") 後,你不能再去碰 "this" 指标了。 

  

    换句话说,你不能查看它、将它与其他指标或是 NULL 相比较、印出其值、 

  

    对它转型、对它做任何事情。 

  

 

  

很自然的,这项警告也适用於:当 "this" 是个指向基底类别的指标,而解构子不是 

  

  

virtual 的场合。 

  

 

  

======================================== 

  

 

  

Q40:我该怎麽用 new 来配置多维阵列? 

  

 

  

有很多方法,端视你对阵列大小的伸缩性之要求而定。极端一点的情形,假如你在编 

  

译期就知道所有阵列的维度,你可以静态地配置(就像 C 一样): 

  

 

  

   class Fred { /*...*/ }; 

  

 

  

   void manipulateArray() 

  

   { 

  

   Fred matrix[10][20]; 

  

 

  

   //使用 matrix[i][j]...

  

精彩图集

赞助商链接