繁体   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