簡體   English   中英

使用 [] 運算符而不是使用 malloc 動態分配數組?

[英]Dynamically allocating array with the [] operator instead of using malloc?

我確信這已經被問了一百萬次,但我找不到解釋它的答案。 有人告訴我永遠不要這樣做,但我真的不明白為什么。 為什么這樣的事情不能算作動態分配 memory ,為什么那么糟糕?

int a;
scanf("%d",&a);
int arr[a];

這不是動態分配,而是可變長度數組

這種數組的生命周期是它封閉的 scope,就像一個固定大小的數組,所以你不需要擔心釋放。 這些 arrays 通常駐留在堆棧中,因此堆棧的大小確實限制了 VLA(或任何陣列)的大小。

如果您發現 VLA 對於堆棧來說太大,您可以隨時退回到使用malloc

使用 [] 運算符而不是使用 malloc 動態分配數組?

這里的[]用於定義一個數組 []這里,不是運算符。

int arr[a];

有人告訴我永遠不要這樣做,但我真的不明白為什么。

這個咒語適用於C(和生活)中的許多東西,在您了解如何使用之前不要使用它。

為什么這樣的事情不能算作動態分配 memory

它動態分配 memory 分配,但通常使用不同的 memory 池並且具有與通過malloc()不同的生命周期。

......為什么它那么糟糕?

int arr[a]; 是一個可變長度數組(VLA),存在以下問題:

  • 並非總是可用。 VLA 在 C99 中支持,並且在以后的版本中經常(但並非總是)支持。 研究__STDC_NO_VLA__

  • 使用int a ,當a <= 0時,代碼是未定義的行為 (UB)。

  • a太大時,沒有標准機制來檢測 memory 不足。

VLA 更好地用於受控的較小尺寸的情況。

首先,讓我告訴您,這稱為變長數組,它是一個可選功能。 最好不要依賴此功能(或編譯器支持)。

另一方面,分配器函數( malloc()free()和 family)符合標准,任何符合標准的編譯器/庫都將支持這些函數。

也就是說,其他答案中提到了差異,主要差異在於 scope 和便攜性。

為什么這樣的事情不能算作動態分配 memory

在運行時確定 object 的大小不足以進行動態分配。 動態分配需要直接或間接使用專門執行動態 memory 分配的函數之一,其中malloccallocrealloc是主要示例。 你的例子...

 int arr[a];

...不這樣做,所以 object 不是動態分配的。 arr是一個或多或少的普通局部變量,具有可變長度數組類型。

從語義上講,動態分配的對象具有“已分配”的存儲持續時間,這意味着它們存在並保留其最后存儲的值,直到顯式釋放。 相反,您的arr具有“自動”存儲持續時間,這意味着當其最內層包含塊的執行終止時它不再存在。

為什么那么糟糕?

意見不一。 VLA 在 C99 中是必需的功能,但在 C11 中支持是可選的。 如果您在代碼中使用 VLA,那么您會限制其可移植性。 C++ 不支持它們(或者至少不支持——我知道它們現在也將使用 C++,也許它們已經到了),這對某些人來說可能是個問題。

但是,引用的主要風險是 VLA 的通常和自然實現是在堆棧上分配它們,並且堆棧大小通常比堆空間更有限。 在像您這樣的幼稚示例中,很容易創建堆棧溢出,這可能取決於用戶輸入,因此既難以測試又存在潛在的安全風險。

確實不時在我的代碼中使用 VLA,但通常以不受上述堆棧破壞風險影響的方式使用。 我通常對“永遠不要那樣做”的告誡持懷疑態度,但實際上我永遠不會編寫您為生產應用程序提供的確切代碼。

這是一個可變長度數組的例子。 它的生命周期與任何其他auto變量(包括固定長度數組)相同,因此一旦退出其封閉的 scope,它的 memory 將被釋放。

與固定長度的 arrays 不同,VLA 不能在文件 scope(在任何函數之外)或使用static關鍵字聲明,也不能使用初始化程序聲明。 由於它們通常是如何管理的,它們不能任意大。 盡管有名稱,但一旦定義它們就無法調整大小 - 可變長度的“變量”僅意味着它們的大小在每次定義時都可以不同。

VLA 有用但有限。 當您需要一些 function 本地的臨時工作存儲並且不需要太大(不超過 1 兆字節左右)時,它們非常有用。

它們僅在 C99 中引入,在 C11 中成為可選,因此對它們的支持可能有點參差不齊。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM