2012-04-17 30 views
4

我有一個簡單的結構:創建對象:在值類型對象內動態分配數據的指針 - 好還是不好?

typedef struct { 
    int width, height; 
    unsigned char *pixels; 
} image; 

哪一個是更好的API?

image *imagecreate(int w, int h) { 
    image *img = malloc(sizeof(image)); 
    img->width = w; 
    img->height = h; 
    img->pixels = calloc(w * h, 3); 
    return img; 
} 

void imagefree(image *img) { 
    free(img->pixels); 
    free(img); 
} 

image imagecreate(int w, int h) { 
    image img; 
    img.width = w; 
    img.height = h; 
    img.pixels = calloc(w * h, 3); 
    return img; 
} 

void imagefree(image *img) { 
    free(img->pixels); 
    img->width = img->height = 0; 
} 

這似乎是矯枉過正做一個額外的malloc()這樣的小結構是隻有大約一個指向真正的動態分配數據的包裝。但另一方面,在一個值類型中隱藏一個指向動態分配內存的指針感覺不自然(對我來說)。有人可能會認爲你不必釋放它。

回答

2

你在談論API。因此,這對您的客戶來說應該很容易正確使用並且難以正確使用

一個小的改進選項#2

例如,如果我是你的第二個API的用戶:

image imagecreate(int w, int h); 
void imagefree(image *img); 

我可能甚至不會注意到需要調用imagefree因爲imagecreate返回一個對象,而不是指向一個對象的指針,而imagefree需要一個指針。我可能認爲imagefree只是堆分配對象的delete image的包裝。所以我不會將它用於「堆棧」對象。

因此,這是更好的:

image imagecreate(int w, int h); 
void imagefree(image img); 

雖然你裏面有一個image堆分配成員,但你把它藏在這些API,這是很好。而且它們具有一致的「外觀」,更好,而且不易出錯。

那麼選項#1呢?

至於你的第一個選擇,那更好嗎?這取決於(對個人)。至於我,我更喜歡選項#1。

image *imagecreate(int w, int h); 
void imagefree(image *img); 

爲什麼?

儘管我們沒有辦法像C++那樣通過析構函數強制執行資源自動銷燬,但通常更多的關注是看到從API返回的「指針」的C程序員(我們對指針敏感,不是嗎?)。很可能他們不斷問自己:它是否在imagecreate內動態分配?我是否需要通過其他API來釋放它?

+0

你說服了我。我可能會使用指針返回值版本。 – ChrG 2012-04-17 11:59:02

1

不同的是,你struct動態在第一情況下,在第二分配和自動。這是個人喜好,編碼標準和意見的問題。第二種方式對我來說似乎比較安全,因爲它要記住要少一個free,但是因爲無論如何你必須使用free - 這並不重要。

注意,在第二種情況下,struct被複制到的返回值。你似乎在處理這個指針,但它是一個潛在的地雷。

+0

我肯定會喜歡第一個,在我看來指針更容易管理。 – Aftnix 2012-04-17 10:10:20

1

我會去的第一個。假設你的struct中有一個descriptor'char name [100]',你的第二個將使用100byte的棧空間,它必須由操作系統來處理,而第一個內存是我自己處理的(使用一個自寫的垃圾收集器代替標準的malloc),你可以隨心所欲地把手柄移動到物體周圍,而無需照顧你有限的堆棧空間。

+0

我通常將字符串作爲char *來管理。但是你是對的,如果我的結構將來會增長,我會浪費更多的堆棧空間。 – ChrG 2012-04-17 11:56:54