简体   繁体   English

如何在 function 中返回值后删除指针

[英]How to delete a pointer after returning its value inside a function

I have this function:我有这个 function:

char* ReadBlock(fstream& stream, int size)
{
    char* memblock;
    memblock = new char[size];
    stream.read(memblock, size);
    return(memblock);
}

The function is called every time I have to read bytes from a file.每次我必须从文件中读取字节时,都会调用 function。 I think it allocates new memory every time I use it but how can I free the memory once I have processed the data inside the array?我认为每次我使用它时它都会分配新的 memory 但是一旦我处理完数组中的数据我怎么能释放 memory 呢? Can I do it from outside the function?我可以从 function 以外的地方进行吗? Processing data by allocating big blocks gives better performance than allocating and deleting small blocks of data?通过分配大块处理数据比分配和删除小块数据提供更好的性能?

Thank you very much for your help!非常感谢您的帮助!

Dynamic arrays are freed using delete[] :使用delete[]释放动态数组:

char* block = ReadBlock(...);
// ... do stuff
delete[] block;

Ideally however you don't use manual memory management here:理想情况下,您不要在这里使用手动内存管理:

std::vector<char> ReadBlock(std::fstream& stream, int size) {
    std::vector<char> memblock(size);
    stream.read(&memblock[0], size);
    return memblock;
}

Just delete[] the return value from this function when you've finished with it.完成此函数后,只需delete[]返回值即可。 It doesn't matter that you're deleting it from outside.你从外面删除它并不重要。 Just don't delete it before you finish using it.在使用完之前不要删除它。

You can call:可以致电:

char * block = ReadBlock(stream, size);
delete [] block;

But... that's a lot of heap allocation for no gain.但是......这是很多没有收益的堆分配。 Consider taking this approach考虑采用这种方法

char *block = new char[size];
while (...) {
  stream.read(block, size);
}
delete [] block;

*Note, if size can be a compile time constant, you can just stack allocate block . *注意,如果size可以是编译时常量,则可以只堆栈分配block

Yes.是的。 You may call delete from outside of the function.您可以从函数外部调用 delete。 In this case though, may I suggest using an std::string so you don't have to worry about the management yourself?不过,在这种情况下,我可以建议使用 std::string 以便您不必自己担心管理吗?

first thing to note: memory allocated with new and delete is completely global.首先要注意:用 new 和 delete 分配的内存是完全全局的。 things are not automatically deleted when pointers go out of scope or a function is exited.当指针超出范围或退出函数时,事物不会自动删除。 as long as you have a pointer to the allocation (such as the pointer being returned there) you can delete it when ever and where ever you want.只要您有一个指向分配的指针(例如在那里返回的指针),您就可以随时随地删除它。 the trick, is just makeing sure other stuff doesn't delete it with out you knowing.诀窍是确保其他内容不会在您不知情的情况下将其删除。

that is a benefit with the sort of function structure the fstream read function has.这是 fstream 读取函数所具有的那种函数结构的好处。 it is fairly clear that all that function is going to do is read 'size' number of bytes into the buffer you provide, it doesn't matter whether that buffer has been allocated using new, whether its a static or global buffer, or even a local buffer, or even just a pointer to a local struct.很明显,该函数要做的就是将“大小”字节数读入您提供的缓冲区中,无论该缓冲区是否已使用 new 分配,无论是静态缓冲区还是全局缓冲区,甚至是一个本地缓冲区,甚至只是一个指向本地结构的指针。 and it is also fairly clear that the function is going to do nothing more with the buffer you pass it once it's read the data to it.并且相当清楚的是,一旦函数将数据读取到它,它就不会对传递给它的缓冲区执行任何操作。

on the other hand, take the structure of your ReadBlock function;另一方面,采用 ReadBlock 函数的结构; if you didn't have the code for that it would be tricky to figure out exactly what it was returning.如果您没有相应的代码,则很难弄清楚它到底返回了什么。 is it returning a pointer to new'd memory?它是否返回一个指向新内存的指针? if so is it expecting you to delete it?如果是这样,是否希望您删除它? will it delete it it's self?它会删除它自己吗? if so, when?如果是这样,什么时候? is it even a new pointer?它甚至是一个新的指针吗? is it just returning an address to some shared static buffer?它只是向某个共享静态缓冲区返回一个地址吗? if so, when will the buffer become invalid (for example, overwritten by something else)如果是这样,缓冲区何时会变得无效(例如,被其他东西覆盖)

looking at the code to ReadBlock, it is clear that it is returning a pointer to new'd memory, and is expecting you to delete it when ever you are done with it.查看 ReadBlock 的代码,很明显它正在返回一个指向新内存的指针,并希望您在完成后将其删除。 that buffer will never be overwritten or become invalid until you delete it.该缓冲区永远不会被覆盖或变为无效,直到您将其删除。

speed wise, thats the other advantage to fsream.read's 'you sort out the buffer' approach: YOU get the choice on when memory is allocated.速度方面,这是 fsream.read 的“你整理缓冲区”方法的另一个优势:你可以选择何时分配内存。 if you are going "read data, process, delete buffer, read data process delete buffer, ect.... " it is going to be alot more efficient to just allocate one buffer (to the maximum size you will need, this will be the size of your biggest single read) and just use that for everything, as suggested by Stephen.如果您要“读取数据、处理、删除缓冲区、读取数据处理删除缓冲区等......”,只分配一个缓冲区会更有效率(到您需要的最大大小,这将是您最大的单次阅读的大小),并按照斯蒂芬的建议将其用于所有内容。

How about using a static char* memblock;使用静态 char* memblock 怎么样? It will be initialised just once and it wont allocate memblock a new space everytime.它只会被初始化一次,并且不会每次都为 memblock 分配一个新空间。

I had a similar question, and produced a simple program to demonstrate why calling delete [] outside a function will still deallocate the memory that was allocated within the function:我有一个类似的问题,并制作了一个简单的程序来演示为什么在函数外调用 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;
}

Here was the resulting readout from this program on my terminal:这是我终端上这个程序的结果读数:

The location of the pointer temppointer is 0x61fdd0.指针临时指针的位置是 0x61fdd0。 Locations pointed to by temppointer: temppointer 指向的位置:

0xfb1f20 holds the value 0. 0xfb1f20 保持值 0。

0xfb1f24 holds the value 1. 0xfb1f24 保持值 1。

0xfb1f28 holds the value 2. 0xfb1f28 保存值 2。

0xfb1f2c holds the value 3. 0xfb1f2c 保存值 3。

The location of the pointer mainpointer is 0x61fe10.指针mainpointer的位置是0x61fe10。 Locations pointed to by mainpointer: mainpointer 指向的位置:

0xfb1f20 holds the value 0. 0xfb1f20 保持值 0。

0xfb1f24 holds the value 1. 0xfb1f24 保持值 1。

0xfb1f28 holds the value 2. 0xfb1f28 保存值 2。

0xfb1f2c holds the value 3. 0xfb1f2c 保存值 3。

This readout demonstrates that although temppointer (created within the allocatememory function) and mainpointer have different values, they point to memory at the same location.该读数表明,虽然 temppointer(在 allocationmemory 函数中创建)和 mainpointer 具有不同的值,但它们指向同一位置的内存。 This demonstrates why calling delete[] for mainpointer will also deallocate the memory that temppointer had pointed to, as that memory is in the same location.这说明了为什么为 mainpointer 调用 delete[] 也会释放 temppointer 指向的内存,因为该内存位于同一位置。

Since c++11, one can use std::unique_ptr for this purpose.自 c++11 以来,可以为此目的使用std::unique_ptr

From https://en.cppreference.com/book/intro/smart_pointers :来自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;
}

But,但,

#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