![](/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.