2014年10月5日 星期日

在函式引數中使用new(C++)

void func(int*);
int main()
{
        func(new int(10));
        return 0;
}
這樣的寫法既不用再多宣告一個int的實體,看起來也很厲害。但我認為這樣的寫法頗有問題。(但是對於JavaC#這類有自動清理機制的程式,就沒關係了。)
撰寫CC++程式時,對動態記憶體的配置(mallocnew)或釋放(freedelete)必須是一對一,否則可能會因為未定義行為而造成非預期的錯誤。
或許有人會說:這麼說來,只要在func內用delete釋放記憶體不就沒問題了。
這樣的答案固然沒錯,但若有一天,其他人要用到func,卻這樣寫:
        int i = 10;
        func(&i);
就造成了釋放stack的情形。或是
        int *p = new int(10);
        func(p);
        delete p;
使得記憶體被釋放了兩次。
如果有人這麼說:要使用我的函式當然要先了解函式內的行為,如果不懂就亂用,錯誤就要自行負責。若真的有人是抱持這種想法,我覺得這種人寫的程式沒有任何價值,因為他已經把函式本身的優點抹煞了。
(函式的優點:使用函式的人只要知道其功能即可,不需要知道其內部運作方式。)
回過頭來看這樣寫的壞處,我歸納為兩點:
1.      new寫在引數中,使得呼叫函式的一方沒有任何指標能存取,故也無法進行delete
2.   函式的引數雖可存取到new產生的空間,但無法確保每次傳入的都是動態記憶體,因此使用delete並不安全。

所以傳入動態記憶體位置時,最好還是配置在已宣告的指標上,再將該指標傳入較為保險。

沒有留言:

張貼留言