哪个运营商删除?
之间有区别吗?
operator delete(some_pointer);
和
delete some_pointer;
如果有的话,区别是什么?应该在哪里使用该运算符的一个版本,在哪里应该使用另一个版本? 谢谢。
Is there a difference between:
operator delete(some_pointer);
and
delete some_pointer;
and if so what is the difference and where one should use one and where the other version of this operator?
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
讽刺的是,
delete
运算符和operator delete()
并不是一回事。delete some_pointer;
调用some_pointer
指向的对象的析构函数,然后调用operator delete()
释放内存。您通常不会直接调用
operator delete()
,因为如果您这样做,则不会调用该对象的析构函数,并且很可能会导致内存泄漏。您唯一需要关心
operator delete()
的情况是当您想通过重写operator new()
和operator delete() 来进行自己的内存管理时
。最重要的是,您还应该知道
delete
和delete []
是两个不同的东西。Ironically, the
delete
operator andoperator delete()
are not the same thing.delete some_pointer;
calls the destructor of the object pointed to bysome_pointer
, and then callsoperator delete()
to free the memory.You do not normally call
operator delete()
directly, because if you do, the object's destructor will not be called, and you are likely to end up with memory leaks.The only time you have to care about
operator delete()
is when you want to do your own memory management by overridingoperator new()
andoperator delete()
.To top it off, you should also be aware that
delete
anddelete []
are two different things.operator delete()
只是释放内存。delete some_pointer
调用some_pointer
的析构函数,然后调用operator delete()
。operator delete()
simply frees the memory.delete some_pointer
callssome_pointer
's destructor, and then callsoperator delete()
.delete some_pointer;
是“正确”使用的。operator delete(some_Pointer);
主要作为定义您自己的删除运算符的语法工件而存在。也就是说,因为您将加号运算符定义为;你确实可以写:
但没有人这样做过。他们使用:
同样,您可以编写
operator delete(some_Pointer);
,但没有人这样做。delete some_pointer;
is the "correct" one to use.operator delete(some_Pointer);
exist mainly as an artifact of the syntax for defining you own delete operator. That is, because you define an plus operator as;you really could write:
but no one ever does that. They use:
Similarly, you could write
operator delete(some_Pointer);
, but no one ever does.至少根据我的经验,实现
operator new
和operator delete
比实际使用(即调用)它们更常见,至少直接地。通常,您间接使用
operator new
和operator delete
——您编写一个new表达式
,例如A *a = new A;
。为了实现这一点,编译器会生成调用operator new
来分配原始内存的代码,然后调用A::A
将该原始内存转换为A< /code> 对象,就像您编写的一样:
使用完该对象后,您可以使用
delete A;
。为了实现这一点,编译器调用对象的 dtor,然后释放内存,大致就像您所做的那样:还有
operator [] new
和operator [] delete
code>,当您分配/删除数组时使用它们 - 但普通版本和数组版本之间不一定有任何真正的区别 - 它们都只是分配指定数量的原始内存(尽管您可能猜测数组版本会分配相对大量的内存,并在此基础上进行一些优化)。无论如何,如果您想优化为特定类的对象分配内存的方式,您可以重载它们来实现这一点。您可以插入并使用相当多的现有实现,特别是对于您希望分配大量微小对象的情况,因此您需要最小化与每次分配相关的开销(例如, HeapLayers,Loki 的小块分配器)。
一个有趣的小趣闻:
operator new
、operator [] new
、operator delete
和operator [] delete总是
static类成员,即使您没有在其声明/定义中显式包含
static`。所有四个都有全局版本(
::operator new
、::operator [] new
、::operator delete
和::运算符[]删除
)。这些标记了“内部”C++ 内存管理与外部世界之间的“边界”。通常,它们从操作系统分配相对较大的内存块,然后根据请求将较小的内存块返回给程序的其余部分。如果您想(尝试)优化整个程序的内存管理,通常可以通过重载(或者实际上是替换)它们来实现。同样,典型的原因是您希望分配大量小对象(但不仅仅是在几个类中)。其中一个示例是 Boost 池图书馆。直接使用上述任何内容通常仅限于需要原始内存块,而不对象的情况。一个例子是实现您自己的容器类。例如,
std::vector
通常使用::operator new
(通过 Allocator 对象)来分配用于存储对象的内存。由于它需要能够分配存储,但只有稍后(或者可能永远不会)在该存储中创建对象,所以它不能只使用像data = new T[size];
这样的东西 - 它必须分配原始内存,然后在将对象添加到集合时(例如,当您push_back
一个对象时),使用placement new 在内存中创建对象。std::deque
也是如此。例如,如果您想“从头开始”实现自己的循环缓冲区,直接处理所有内存管理,而不是使用vector
之类的东西进行存储,您可能需要/想要做同样的事情。At least in my experience, it's more common to implement
operator new
andoperator delete
than to actually use (i.e., call) them, at least directly.Usually, you use
operator new
andoperator delete
indirectly -- you write anew expression
, likeA *a = new A;
. To implement this, the compiler generates code that invokesoperator new
to allocate raw memory, then invokes aA::A
to convert that raw memory into anA
object, much as if you'd written:When you're done with the object, you use
delete A;
. To implement that, the compiler invokes the dtor for the object, and then frees the memory, roughly like you'd done:There are also
operator [] new
andoperator [] delete
, which are used when/if you allocate/delete arrays -- but there isn't necessarily any real difference between the normal version and the array version -- they both just allocate a specified amount of raw memory (though you might guess that the array versions will allocate relatively large amounts of memory, and do some optimization on that basis).In any case, if you want to optimize how memory is allocated for objects of a particular class you overload these to do it. There are a fair number of existing implementations that you can drop-in and use, especially for situations where you expect to allocate a large number of tiny objects so you need to minimize the overhead associated with each allocation (e.g., HeapLayers, Loki's small block allocator).
One interesting little tidbit:
operator new
,operator [] new
,operator delete
and operator [] deleteare always
staticclass members, even if you don't explicitly include
static` in their declaration/definition.There are also global versions of all four (
::operator new
,::operator [] new
,::operator delete
and::operator [] delete
). These mark the "border" between the "internal" C++ memory management, and the outside world. Typically they allocate relatively large chunks of memory from the operating system, and then return smaller pieces to the rest of the program upon request. If you want to (try to) optimize memory management for your entire program, you typically do it by overloading (or, really, replacing) these. Again, the typical reason would be if you expect to allocate a lot of small objects (but not in just a few classes). One example of this is the Boost Pool library.Direct use of any of the above is generally restricted to situations where you need a block of raw memory, not objects. One example would be implementing your own container classes. For example,
std::vector
normally uses::operator new
(via an Allocator object) to allocate memory in which to store objects. Since it needs to be able to allocate storage, but only later (or perhaps never) create objects in that storage, it can't just use something likedata = new T[size];
-- it has to allocate raw memory, then use placement new to create objects in the memory as you add them to the collection (e.g., when youpush_back
an object). The same is true withstd::deque
. If you wanted (for example) to implement your own circular buffer "from the ground up", handling all the memory management directly instead of using something likevector
for storage, you'd probably need/want to do the same.