新建和删除放置
删除此处分配的所有内存的正确方法是什么?
const char* charString = "Hello, World";
void *mem = ::operator new(sizeof(Buffer) + strlen(charString) + 1);
Buffer* buf = new(mem) Buffer(strlen(charString));
delete (char*)buf;
或者
const char* charString = "Hello, World";
void *mem = ::operator new(sizeof(Buffer) + strlen(charString) + 1);
Buffer* buf = new(mem) Buffer(strlen(charString));
delete buf;
它们都是一样的?
What is the right method to delete all the memory allocated here?
const char* charString = "Hello, World";
void *mem = ::operator new(sizeof(Buffer) + strlen(charString) + 1);
Buffer* buf = new(mem) Buffer(strlen(charString));
delete (char*)buf;
OR
const char* charString = "Hello, World";
void *mem = ::operator new(sizeof(Buffer) + strlen(charString) + 1);
Buffer* buf = new(mem) Buffer(strlen(charString));
delete buf;
or are they both same?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
正确的方法是:
您只能使用
delete
operator删除从new
operator收到的内容。如果直接调用operator new函数,则还必须直接调用operator delete函数,并且还必须手动调用析构函数。The correct method is:
You can only delete with the
delete
operator what you received from thenew
operator. If you directly call theoperator new
function, you must also directly call theoperator delete
function, and must manually call the destructor as well.C++ 中有两个独立的概念:
新建/删除运算符。
新建/删除表达式。
运算符分配和释放内存。
new
表达式构造对象。delete
表达式有时会销毁对象并调用运算符。为什么是“有时”?因为这取决于表达方式。裸露的全局
new
首先调用operator-new分配内存,然后构造对象;全局删除调用析构函数并释放内存。但new
和delete
的所有其他重载都是不同的:New/Delete 运算符仍然必须在匹配对中重载,因为当对象构造函数抛出异常时,会调用匹配的删除运算符。但是,对于使用重载的 new 运算符分配的对象,没有自动调用析构函数的方法,因此您必须自己执行此操作。
作为第一个也是最基本的示例,请考虑放置新运算符,它被强制采用
void * operator new (size_t, void * p) throw() { return p; } 的形式。 }
。因此,匹配的删除操作符被强制不执行任何操作:void操作符delete (void *, void *) throw() { }。用法:There are two separate notions in C++:
The new/delete operators.
New/Delete expressions.
The operators allocate and deallocate memory. The
new
expression constructs objects. Thedelete
expression sometimes destroys an object and calls the operator.Why "sometimes"? Because it depends on the expression. The naked, global
new
first calls operator-new to allocate memory and then constructs the object; the globaldelete
calls the destructor and deallocates the memory. But all other overloads ofnew
anddelete
are different:New/Delete operators still have to be overloaded in matching pairs, because the matching delete operator is called when an object constructor throws an exception. However, there is no automatic way to invoke the destructor for an object that has been allocated with an overloaded
new
operator, so you have to do that yourself.As the first and most basic example, consider the placement-new operator, which is mandated to take the form
void * operator new (size_t, void * p) throw() { return p; }
. The matchingdelete
operator is thus mandated to do nothing:void operator delete (void *, void *) throw() { }
. Usage:正如其他答案中所解释的,更好、更明智的方法是
但是,假设没有
Buffer::operator delete
这样的东西,则delete buf;
版本在技术上是可以的,并且将进行所有相同的清理。为了避免Buffer::operator delete
的可能性,您可以说::delete buf;
。语言律师辩论材料如下。
5.3.5/1
5.3.5/2
所以指针必须指向一个由new-表达式创建的对象,其定义为:
5.3.4/1
因此,“placement new”确实算作新表达式。没有什么禁止那里的删除表达式。
此外,事实证明,尽管是自定义创建的,但删除表达式确实做了正确的事情来清理对象。
5.3.5/6-9
所以
::delete buf;
完全等同于:The better and saner way, as explained in other answers, is
However, assuming there's no such thing as
Buffer::operator delete
, thedelete buf;
version is technically okay and will do all the same cleanup. To avoid theBuffer::operator delete
possibility, you can say::delete buf;
.Language-lawyer debate material follows.
5.3.5/1
5.3.5/2
So the pointer must point at an object created by a new-expression, which is defined:
5.3.4/1
So a "placement new" does count as a new-expression. Nothing forbidding a delete-expression there.
Also, it turns out the delete-expression does exactly the right things to clean up the object despite the custom creation.
5.3.5/6-9
So
::delete buf;
is entirely equivalent to: