FAQ 2.07
C++允許用new指標動態分配記憶體,動態分配也就是從堆分配。下面顯示了用文法new Car()從堆分配Car對象。結果被存在一個CarPtr指標中,CarPtr是一個auto_ptr的別名,這是一種"安全指標類型"。typedef文法建立了相對應的別名。
#include <memory> <-- 1#include <string>using namespace std;#include "Car.hpp"typedef auto_ptr<Car> CarPtr;void f(){ CarPtr p(new Car()); <-- 1 p->startEngine(); <-- 2 p->tuneRadioTo("AM", 770); <-- 3} <-- 4int main(){ f();}
(1) auto_ptr定義所在的標頭檔
(1)1.建立一個對象。
(2)2.調用一個成員函數
(3)3.調用另外一個成員函數
(4)4.銷毀Car對象。
當控制流程經過列標籤1.建立一個對象,一個對象被動態建立(從堆),指標P指向了對象。從對象CarPtr被建立到對象CarPtr在}(第4行)被銷毀之前對象可以一直被訪問。注意CarPtr能被返回到調用者。這一行類似於(但是不能互相代替)C代碼P = malloc(sizeof(Car)).注意參數能被傳遞到構造器中,例如P = new Car(100, 73);
當控制流程經過列標籤2:調用一個成員函數,startEngine()成員函數被對象指標P調用。列標籤3:調用另一個成員函數,展示如何給動態分配的對象傳遞參數。
當控制流程經過列標籤4.銷毀Car對象, P指向的Car對象被銷毀,如果Car類有一個析構器,控制流程經過這一行的時候運行時系統調用析構器。
注意動態指派至不必在建立對象的地區中銷毀。例如,函數中的return p;,Car對象的所有權被返回給調用者,它的意思是
Car對象直到到達調用者的}才被銷毀(或者調用者的調用者...):
CarPtr g()
{
CarPtr p(new Car());
// ...
return p; <-- 1
}
void h()
{
CarPtr p = g(); <-- 2
// ...
} <-- 3
(1) 調用者負責刪除Car對象。
(2) 所有者從g()轉移到了h()
(3)Car對象在這而銷毀
C程式員要注意:
用未處理過的Car *指標控制new Car()操作通常被認為是不好的形式。這種方式相對於傳統的C語言中指標來說是一種巨大的變化。
C++方法使"記憶體流失"更少(沒有顯示的free(p)或者delete p,所以程式員不用擔心忘記釋放記憶體),
C++使"懸Null 參考" (dangling references)更少(如果C-Like Car * 指標被使用,就可能訪問被刪除的Car 對象)‘
C++方法使代碼更容易"安全除錯"(exception safe)(如果一個C-like Car *被使用,任何拋出異常的程式都必須使用try...catch封裝塊)。