[英]realloc function that would work for memory allocated using new instead of realloc
[英]Is it safe to realloc memory allocated with new?
從這里所寫的內容來看, new
在自由存儲中分配,而malloc
使用堆,這兩個術語通常意味着相同的事情。
從這里寫的內容來看, realloc
可能會將內存塊移動到新位置。 如果 free store 和 heap 是兩個不同的內存空間,那么這是否意味着任何問題?
具體來說,我想知道使用是否安全
int* data = new int[3];
// ...
int* mydata = (int*)realloc(data,6*sizeof(int));
如果沒有,是否有任何其他方式來realloc
內存分配的new
安全? 我可以分配新區域並memcpy
內容,但據我所知,如果可能, realloc
可能會使用相同的區域。
您只能realloc
是對已經通過分配malloc
(或家庭,如calloc
)。
這是因為跟蹤空閑和已用內存區域的底層數據結構可能大不相同。
可能但絕不保證 C++ new
和 C malloc
使用相同的底層分配器,在這種情況下realloc
可以對兩者都有效。 但正式地說,那是在UB-land。 在實踐中,這只是不必要的風險。
C++ 不提供對應於realloc
功能。
最接近的是像std::vector
這樣的容器(的內部緩沖區)的自動重新分配。
C++ 容器的設計方式不包括realloc
使用。
而不是呈現的代碼
int* data = new int[3];
//...
int* mydata = (int*)realloc(data,6*sizeof(int));
… 做這個:
vector<int> data( 3 );
//...
data.resize( 6 );
但是,如果您絕對需要realloc
的一般效率,並且如果您必須接受new
用於原始分配,那么您唯一的效率方法就是使用特定於編譯器的方法,了解realloc
對於此編譯器是安全的。
否則,如果您絕對需要realloc
的一般效率但又不被迫接受new
,那么您可以使用malloc
和realloc
。 使用智能指針可以讓您獲得與使用 C++ 容器相同的安全性。
C++ 對realloc
添加的唯一可能相關的限制是 C++ 的malloc
/ calloc
/ realloc
不能在::operator new
方面實現,它的free
不能在::operator delete
方面實現(根據 C++14 [ c.malloc]p3-4)。
這意味着您正在尋找的保證在 C++ 中不存在。 但是,這也意味着您可以根據malloc
實現::operator new
。 如果你這樣做,那么理論上, ::operator new
的結果可以傳遞給realloc
。
在實踐中,您應該擔心new
的結果與::operator new
的結果不匹配的可能性。 例如,C++ 編譯器可以組合多個new
表達式以使用單個::operator new
調用。 這是編譯器在標准不允許的情況下已經做的事情,IIRC,現在標准允許它(根據 C++14 [expr.new]p10)。 這意味着即使你走這條路,你仍然不能保證將你的new
指針傳遞給realloc
做任何有意義的事情,即使它不再是未定義的行為。
一般來說,不要這樣做。 如果您使用具有非平凡初始化的用戶定義類型,則在重新分配復制釋放的情況下,您的對象的析構函數將不會被realloc
調用。 復制時也不會調用復制構造函數。 由於對象生命周期的不正確使用,這可能會導致未定義的行為(參見C++ 標准 §3.8 對象生命周期,[basic.life] )。
1 對象的生命周期是對象的運行時屬性。 如果一個對象屬於類或聚合類型,並且它或它的一個成員是由一個非平凡默認構造函數初始化的構造函數,則稱該對象具有非平凡初始化。 [ 注意:通過簡單的復制/移動構造函數初始化是非平凡的初始化。 ——尾注]
類型 T 的對象的生命周期在以下情況下開始:
— 獲得了類型 T 具有正確對齊和大小的存儲,並且
— 如果對象具有非平凡的初始化,則其初始化已完成。
類型 T 的對象的生命周期在以下情況下結束:
— 如果 T 是具有非平凡析構函數的類類型 (12.4),則析構函數調用開始,或
— 對象占用的存儲空間被重用或釋放。
后來(強調我的):
3 本國際標准中賦予對象的屬性僅適用於給定對象在其生命周期內。
所以,你真的不想在一個對象的生命周期之外使用它。
它不安全,也不優雅。
可能可以覆蓋 new/delete 以支持重新分配,但您也可以考慮使用容器。
一般來說,沒有。
有很多事情必須堅持以確保安全:
平凡類型滿足上述要求。
此外:
new[]
- 函數必須將請求不作任何更改地傳遞給malloc
,也不做任何簿記。 您可以通過替換全局 new[] 和 delete[] 或相應類中的替換來強制執行此操作。是的 - 如果new
實際上首先調用malloc
(例如,這就是 VC++ new
工作方式)。
沒有別的。 請注意,一旦您決定重新分配內存(因為new
稱為malloc
),您的代碼是特定於編譯器的,並且不再在編譯器之間移植。
(我知道這個答案可能會讓許多開發人員感到不安,但我的答案取決於實際情況,而不僅僅是慣用語)。
那是不安全的。 首先,您傳遞給realloc
的指針必須是從malloc
或realloc
獲得的: http : //en.cppreference.com/w/cpp/memory/c/realloc 。
其次, new int [3]
的結果不必與分配函數的結果相同——可以分配額外的空間來存儲元素的數量。
(對於比int
更復雜的類型, realloc
不安全,因為它不調用復制或移動構造函數。)
您可能能夠(並非在所有情況下),但您不應該這樣做。 如果您需要調整數據表的大小,則應改用std::vector
。
其他SO 問題中列出了有關如何使用它的詳細信息。
這些函數主要用在 C 中。
memset 將內存塊中的字節設置為特定值。
malloc 分配一塊內存。
calloc,與 malloc 相同。 唯一的區別是它將字節初始化為零。
在 C++ 中,分配內存的首選方法是使用 new。
C: int intArray = (int*) malloc(10 *sizeof(int)); C++:int intArray = new int[10];
C: int intArray = (int*) calloc(10 *sizeof(int)); C++: int intArray = new int10;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.