我在复习一些我已经用了很长时间来处理二进制字符数组数据的代码时,脑子里突然出现了这个问题。
如果myBinaryDataArray填充了二进制数据(包括"\0"字符),下面的半伪C++代码是否准确地将其从堆中释放?我确信某个地方有文件,但我搜索了几次,没有找到结果——可能是我的措辞。
代码示例:
char* myBinaryDataArray = new char[someLengthMyProgramNeeds];
/* mBinaryDataArray filled with binary data */
delete[] myBinaryDataArray;
我一直认为delete知道如何正确删除,但最近我在从方法返回一些对象后遇到了删除问题(我注意到没有调用析构函数)。我现在开始质疑我是否正确使用了它。
有人对删除或它的工作原理有很好的资源或解释吗?在使用它时我应该记住什么?
也只是为了确保不是我。如果有人能让我知道对对象的返回堆分配指针调用delete是否不正确,为什么不呢?我发现一些东西可以通过删除它的强制转换来编译,指向它应该是的类型的指针,但我不知道这是否正确。我想我读到了一些关于它的内容,但本质上我想了解更多关于C++中删除的信息。
只要指针完好无损,是否从函数调用返回指针没有区别。对象指针中的唯一更改应该通过支持的强制转换来完成。
即使new
和delete
是类型感知的,它们仍然基于分配器,并且依赖于从new
传递回delete
的原始指针。把new
和delete
想象成图书馆或视频租赁店的同一个柜台。
正确的做法是只使用new
或new[]
分配的delete
对象,或者让智能指针负责为您删除。
new
通常应该进入构造函数,delete
应该进入相应的析构函数,但可以在工厂方法或其他任何地方。
C++虚拟析构函数的原因是允许正确删除多态类型。只要Base和Derived实现正确的虚拟析构函数,所有类托管资源都将正确释放。
析构函数将根据类型信息执行,但析构函数中的任何代码都将在原始对象位于指针地址的假设下运行。分配器使用一种类似于伙伴系统的算法,该算法依赖于指针所在的位置,以及存储在对象相对偏移处的记账信息。如果向delete
传递一个已更改的指针,则这是一个错误,通常会损坏堆。
#include <iostream>
class foo {
public:
~foo() { std::cout << "Destructor called" << std::endl; }
};
class bar {
public:
foo* myMethod() { return new foo(); }
};
int main(int argc, char** argv)
{
bar b;
foo* f = b.myMethod();
delete f;
}
输出:
Destructor called
响应:
也只是为了确保不是我。如果有人能让我知道对对象的返回堆分配指针调用delete是否不正确,为什么不呢?我发现一些东西可以通过删除它的强制转换来编译,指向它应该是的类型的指针,但我不知道这是否正确。我想我读到了一些关于它的内容,但本质上我想了解更多关于C++中删除的信息。
以下半伪C++代码是否准确释放如果堆中填充了二进制数据,则从堆中取出myBinaryDataArray(包括"\0"字符)?
没有。如果在调用delete[]
之前发生异常或其他控制流事件(返回),则它将泄漏。
我一直认为delete知道如何删除正确,但我最近在删除某些对象时遇到了问题在它们从一个方法返回之后(我注意到了析构函数未被调用)。我现在开始怀疑我是否在使用它正确地
如果你自己调用delete[]
或delete
,那么最有可能的是你没有正确使用它。CCD_ 16和CCD_。
有人对删除或如何删除有很好的资源或解释吗有效,使用时应该记住什么?
没有什么需要记住的,因为没有必要使用delete
。对于库实现者来说,它是一个有用的基元。它上几乎所有有用的高级API都是作为标准提供的。
即使你有一些令人信服的用例,而vector
或unique_ptr
/shared_ptr
和Boost中的朋友完全不可能解决这些用例,这是极不可能的,但仍然没有动机使用delete
,因为任何值得使用的API都会使用deleter函数,而标准已经为delete
提供了一个。