C语言中的free和C ++中的delete之间的区别? [英] The differences between free in C and delete in C++?

查看:461
本文介绍了C语言中的free和C ++中的delete之间的区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道 C 中的空闲操作是告诉编译器该特定的内存块是免费的,供编译器用于进一步分配,但不释放内存。

I know the free operation in C is to tell the compiler this particular memory block is free for compiler to use for further allocation, but the memory is not released.

在C ++中删除怎么办?

What about the delete in C++? the same as free?

推荐答案

在其中有两个删除概念C ++:一个是 operator ,声明为 :: operator delete(void *),它基本上只释放内存,通常不释放大多数程序员都想到过。另一个是 delete表达式 delete p; ,其中 p T * 。该表达式调用 p 指向的对象的析构函数(然后释放内存),这是C ++的重要语言功能,在C中没有类似物。

There are two notions of delete in C++: One is the operator, declared as ::operator delete(void*), which basically only frees up the memory and isn't usually thought about by most programmers. The other is the delete expression, delete p;, where p is a T*. The expression invokes the destructor of the object pointed to by p (and then frees the memory), which is a crucial language feature of C++ that has no analogue in C.

根据经验,将表达式与删除表达式以及 malloc()函数调用和 free()函数调用:

As a rule of thumb, you pair new expressions with delete expressions, and malloc() function calls with free() function calls:

T * p = new T;        // constructor called!
delete p;             // destructor called!

void * x = malloc(5); // just raw memory
free(x);              // freed






高级部分(不响应OP的问题)

C ++中的动态对象生存期遵循以下一般模式:分配,构造,销毁,释放。标准的 new 表达式执行分配和构造,而标准的 delete 表达式执行销毁和释放。

Dynamic object lifetime in C++ follows this general pattern: Allocate, construct, destroy, deallocate. The standard new expression performs allocation and construction, while the standard delete expression performs destruction and deallocation.

您可以手动写出该过程:

You could write out the process manually:

T * p = (T*)::operator new(sizeof(T));   // allocate raw memory
p = new (p) T;                           // call the constructor ("placement new")

/*...*/

p->~T();                                 // destroy the object
::operator delete(p);                    // deallocate the memory

实际上,如果您确实想实现Baby's First C ++,则可以定义操作符,就像 malloc / 免费

In fact, if you really wanted to implement Baby's First C++, you could define the operators as just as malloc/free:

void * operator new(size_t n) { return malloc(n); }
void   operator delete(void * p) { free(p); }

真正的C ++神奇之处在于 new delete 表达式:标准的 new 表达式将调用构造函数(分配后,code> new 表达式是在C ++中调用构造器的唯一方法!),而标准delete表达式在释放之前调用析构函数。

The real C++ magic happens by virtue of the new and delete expressions: The standard new expression invokes the constructor (a new expression is the only way to call a constructor in C++!) after allocation, while the standard delete expression invokes the destructor before deallocation.

为什么要使用标准表达式?好了,您还可以定义并重载许多其他版本的 new delete 运算符。但是,存在一个重要的不对称性:虽然您可以在自定义的 new 表达式中使用自定义的 new 运算符(通常称为 placement new),没有等效的 placement-delete表达式。因此,无论何时使用自定义 new 表达式,都必须在调用匹配的自定义删除 operator

Why "standard expression"? Well, you can also define and overload many other versions of new and delete operators. However, there is an important asymmetry: While you can use a custom new operator in a custom new expression (generally dubbed "placement new"), there is no equivalent "placement-delete" expression. So whenever you use a custom new expression, you have to manually invoke the destructor before calling the matching custom delete operator:

T * p = new (A, B, C) T;                          // some custom new expression

// Entirely equivalent version:

T * p = (T*) ::operator new(sizeof(T), A, B, C);  // this is your custom overload
T * p = new (p) T;                                // std. placement-new expression calls constructor

/* ---- later ---- */

p->~T();                                          // Must destroy manually!
::operator delete(p, A, B, C);                    // your matching custom overload

请注意,不存在自定义删除表达式删除(A,B,C)p'

Note that there does not exist a custom delete expression delete (A,B,C) p'!

为了完整起见,请使用标准位置新运算符,标准要求其唯一目的是调用构造函数,

For completeness, the standard placement new operator, whose only purpose is to call a constructor, is mandated by the standard to take the following form:

void * operator new(size_t, void * p) { return p; }

它与 delete operator相匹配也被强制使用,名称不能执行任何操作:

It's matching delete operator is also mandated, name to do nothing:

void operator delete(void * p, void *) { }

您可以在上面的一般示例中看到为什么这样做是必要的。

You can see in the above general example why this is necessary.

始终要成对重载 new delete 的自定义版本,这一点很重要!原因是,如果对象构造因构造函数内部的异常而失败,则通过调用 delete 运算符(与有问题的 new 表达式。

It is important always to overload custom versions of new and delete in pairs! The reason is that if the object construction fails with an exception inside the constructor, then the memory is released by a call to the delete operator that matches the offending new expression.

第二次更新: -安全,我们必须考虑 T 的构造函数可能会抛出:

Second update: To be exception-safe, we have to consider that the constructor of T might throw:

版本1:

try {
  T * p = new (A, B, C) T;
  /* ... */
  p->~T();
  ::operator delete(p, A, B, C); // automatically invoked if T::T() throws!
}
catch(...) { }

版本2:

void * addr = ::operator new(sizeof(T), A, B, C);
try {
  T * p = new (addr) T;  // might throw
  /* ... */
  p->~T();
  // ::operator delete(p, addr); // ditto as in (1), but does nothing
}
catch(...) { }
::operator delete(addr, A, B, C);

这篇关于C语言中的free和C ++中的delete之间的区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆