簡體   English   中英

如何在 function 中返回值后刪除指針

[英]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.

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