![](/img/trans.png)
[英]Is the pointer guaranteed to preserve its value after `delete` in C++?
[英]How to delete a pointer after returning its value inside a function
我有這個 function:
char* ReadBlock(fstream& stream, int size)
{
char* memblock;
memblock = new char[size];
stream.read(memblock, size);
return(memblock);
}
每次我必須從文件中讀取字節時,都會調用 function。 我認為每次我使用它時它都會分配新的 memory 但是一旦我處理完數組中的數據我怎么能釋放 memory 呢? 我可以從 function 以外的地方進行嗎? 通過分配大塊處理數據比分配和刪除小塊數據提供更好的性能?
非常感謝您的幫助!
使用delete[]
釋放動態數組:
char* block = ReadBlock(...);
// ... do stuff
delete[] block;
理想情況下,您不要在這里使用手動內存管理:
std::vector<char> ReadBlock(std::fstream& stream, int size) {
std::vector<char> memblock(size);
stream.read(&memblock[0], size);
return memblock;
}
完成此函數后,只需delete[]
返回值即可。 你從外面刪除它並不重要。 在使用完之前不要刪除它。
您可以致電:
char * block = ReadBlock(stream, size);
delete [] block;
但是......這是很多沒有收益的堆分配。 考慮采用這種方法
char *block = new char[size];
while (...) {
stream.read(block, size);
}
delete [] block;
*注意,如果size
可以是編譯時常量,則可以只堆棧分配block
。
是的。 您可以從函數外部調用 delete。 不過,在這種情況下,我可以建議使用 std::string 以便您不必自己擔心管理嗎?
首先要注意:用 new 和 delete 分配的內存是完全全局的。 當指針超出范圍或退出函數時,事物不會自動刪除。 只要您有一個指向分配的指針(例如在那里返回的指針),您就可以隨時隨地刪除它。 訣竅是確保其他內容不會在您不知情的情況下將其刪除。
這是 fstream 讀取函數所具有的那種函數結構的好處。 很明顯,該函數要做的就是將“大小”字節數讀入您提供的緩沖區中,無論該緩沖區是否已使用 new 分配,無論是靜態緩沖區還是全局緩沖區,甚至是一個本地緩沖區,甚至只是一個指向本地結構的指針。 並且相當清楚的是,一旦函數將數據讀取到它,它就不會對傳遞給它的緩沖區執行任何操作。
另一方面,采用 ReadBlock 函數的結構; 如果您沒有相應的代碼,則很難弄清楚它到底返回了什么。 它是否返回一個指向新內存的指針? 如果是這樣,是否希望您刪除它? 它會刪除它自己嗎? 如果是這樣,什么時候? 它甚至是一個新的指針嗎? 它只是向某個共享靜態緩沖區返回一個地址嗎? 如果是這樣,緩沖區何時會變得無效(例如,被其他東西覆蓋)
查看 ReadBlock 的代碼,很明顯它正在返回一個指向新內存的指針,並希望您在完成后將其刪除。 該緩沖區永遠不會被覆蓋或變為無效,直到您將其刪除。
速度方面,這是 fsream.read 的“你整理緩沖區”方法的另一個優勢:你可以選擇何時分配內存。 如果您要“讀取數據、處理、刪除緩沖區、讀取數據處理刪除緩沖區等......”,只分配一個緩沖區會更有效率(到您需要的最大大小,這將是您最大的單次閱讀的大小),並按照斯蒂芬的建議將其用於所有內容。
使用靜態 char* memblock 怎么樣? 它只會被初始化一次,並且不會每次都為 memblock 分配一個新空間。
我有一個類似的問題,並制作了一個簡單的程序來演示為什么在函數外調用 delete [] 仍然會釋放在函數內分配的內存:
#include <iostream>
#include <vector>
using namespace std;
int *allocatememory()
{
int *temppointer = new int[4]{0, 1, 2, 3};
cout << "The location of the pointer temppointer is " << &temppointer << ". Locations pointed to by temppointer:\n";
for (int x = 0; x < 4; x++)
cout << &temppointer[x] << " holds the value " << temppointer[x] << ".\n";
return temppointer;
}
int main()
{
int *mainpointer = allocatememory();
cout << "The location of the pointer mainpointer is " << &mainpointer << ". Locations pointed to by mainpointer:\n";
for (int x = 0; x < 4; x++)
cout << &mainpointer[x] << " holds the value " << mainpointer[x] << ".\n";
delete[] mainpointer;
}
這是我終端上這個程序的結果讀數:
指針臨時指針的位置是 0x61fdd0。 temppointer 指向的位置:
0xfb1f20 保持值 0。
0xfb1f24 保持值 1。
0xfb1f28 保存值 2。
0xfb1f2c 保存值 3。
指針mainpointer的位置是0x61fe10。 mainpointer 指向的位置:
0xfb1f20 保持值 0。
0xfb1f24 保持值 1。
0xfb1f28 保存值 2。
0xfb1f2c 保存值 3。
該讀數表明,雖然 temppointer(在 allocationmemory 函數中創建)和 mainpointer 具有不同的值,但它們指向同一位置的內存。 這說明了為什么為 mainpointer 調用 delete[] 也會釋放 temppointer 指向的內存,因為該內存位於同一位置。
自 c++11 以來,可以為此目的使用std::unique_ptr
。
來自https://en.cppreference.com/book/intro/smart_pointers :
void my_func()
{
int* valuePtr = new int(15);
int x = 45;
// ...
if (x == 45)
return; // here we have a memory leak, valuePtr is not deleted
// ...
delete valuePtr;
}
但,
#include <memory>
void my_func()
{
std::unique_ptr<int> valuePtr(new int(15));
int x = 45;
// ...
if (x == 45)
return; // no memory leak anymore!
// ...
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.