C语言中的free和c++中的delete之间有什么区别?

时间:2023-02-06 22:32:53

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++中的delete呢?一样*?

4 个解决方案

#1


18  

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.

在c++中有两个delete的概念:一个是操作符,声明为:::操作符delete(void*),它基本上只释放内存,大多数程序员通常不会考虑它。另一个是delete表达式,delete p;,其中p是T*。表达式调用p指向的对象的析构函数(然后释放内存),这是c++的一个关键语言特性,在C语言中没有类似的东西。

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

根据经验,您可以使用delete表达式对新表达式进行配对,使用free()函数调用malloc()函数调用:

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

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

Advanced part (not in response to the OP's question)

高级部分(不是针对OP的问题)

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.

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

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

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

事实上,如果您真的想实现Baby的第一个c++,您可以将操作符定义为malloc/free:

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

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.

真正的c++魔法是通过新的和delete表达式实现的:标准的新表达式在分配之后调用构造函数(在c++中,调用构造函数的唯一方法是新的表达式),而标准的delete表达式在释放之前调用析构函数。

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

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

注意,不存在自定义删除表达式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; }

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.

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

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.

总是很重要的是重载自定义版本的新和删除对!原因是,如果对象构造失败,构造函数中有一个异常,则通过调用与出错的新表达式匹配的delete操作符释放内存。


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

第二次更新:为了避免异常,我们必须考虑T的构造函数可能抛出:

Version 1:

版本1:

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

Version 2:

版本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);

#2


2  

delete is the same (ish) as free, but has important differences. The most notable difference is that delete will run an objects destructor whereas free won't.

删除和免费一样(有点),但有重要的区别。最显著的区别是delete将运行对象析构函数,而free则不会。

As the comments point out, another very important detail is not mixing malloc/free and new/delete. If you allocate with malloc, use free and similarly if you use new, use delete!

正如评论指出的,另一个非常重要的细节是没有混合malloc/free和new/delete。如果您使用malloc进行分配,请使用free,如果您使用new,请使用delete!

#3


0  

They are not the same. The delete operator in C++ calls the object's destructor, which, depending on the implementation, should release the memory. The delete function can also be overloaded, where free cannot.

他们不一样。c++中的delete操作符调用对象的析构函数,根据实现的不同,它应该释放内存。delete函数也可以重载,而free不能重载。

#4


0  

malloc() and free() are not to be used in C++ code because they don't support object semantics. Furthermore, the results of calling free() to release an object that was allocated by new, or of using delete to release memory that was allocated by malloc(), are undefined. The C++ standard doesn't guarantee that the underlying implementation of operator new uses malloc(); in fact, on some implementations malloc() and new use different heaps. Check this link

malloc()和free()不能在c++代码中使用,因为它们不支持对象语义。此外,调用free()来释放一个由new分配的对象,或者使用delete来释放malloc()分配的内存的结果是没有定义的。c++标准不保证操作员新实现的底层实现使用malloc();事实上,在某些实现上malloc()和new使用不同的堆。检查这个链接

delete() would delete the entire memory space occupied making it imposible to refer the varaiable once its gets deleted where in free() u could still access it.

删除()将删除占用的整个内存空间,使其无法在空闲时()仍然可以访问它时引用varaiable。

#1


18  

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.

在c++中有两个delete的概念:一个是操作符,声明为:::操作符delete(void*),它基本上只释放内存,大多数程序员通常不会考虑它。另一个是delete表达式,delete p;,其中p是T*。表达式调用p指向的对象的析构函数(然后释放内存),这是c++的一个关键语言特性,在C语言中没有类似的东西。

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

根据经验,您可以使用delete表达式对新表达式进行配对,使用free()函数调用malloc()函数调用:

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

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

Advanced part (not in response to the OP's question)

高级部分(不是针对OP的问题)

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.

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

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

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

事实上,如果您真的想实现Baby的第一个c++,您可以将操作符定义为malloc/free:

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

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.

真正的c++魔法是通过新的和delete表达式实现的:标准的新表达式在分配之后调用构造函数(在c++中,调用构造函数的唯一方法是新的表达式),而标准的delete表达式在释放之前调用析构函数。

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

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

注意,不存在自定义删除表达式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; }

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.

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

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.

总是很重要的是重载自定义版本的新和删除对!原因是,如果对象构造失败,构造函数中有一个异常,则通过调用与出错的新表达式匹配的delete操作符释放内存。


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

第二次更新:为了避免异常,我们必须考虑T的构造函数可能抛出:

Version 1:

版本1:

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

Version 2:

版本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);

#2


2  

delete is the same (ish) as free, but has important differences. The most notable difference is that delete will run an objects destructor whereas free won't.

删除和免费一样(有点),但有重要的区别。最显著的区别是delete将运行对象析构函数,而free则不会。

As the comments point out, another very important detail is not mixing malloc/free and new/delete. If you allocate with malloc, use free and similarly if you use new, use delete!

正如评论指出的,另一个非常重要的细节是没有混合malloc/free和new/delete。如果您使用malloc进行分配,请使用free,如果您使用new,请使用delete!

#3


0  

They are not the same. The delete operator in C++ calls the object's destructor, which, depending on the implementation, should release the memory. The delete function can also be overloaded, where free cannot.

他们不一样。c++中的delete操作符调用对象的析构函数,根据实现的不同,它应该释放内存。delete函数也可以重载,而free不能重载。

#4


0  

malloc() and free() are not to be used in C++ code because they don't support object semantics. Furthermore, the results of calling free() to release an object that was allocated by new, or of using delete to release memory that was allocated by malloc(), are undefined. The C++ standard doesn't guarantee that the underlying implementation of operator new uses malloc(); in fact, on some implementations malloc() and new use different heaps. Check this link

malloc()和free()不能在c++代码中使用,因为它们不支持对象语义。此外,调用free()来释放一个由new分配的对象,或者使用delete来释放malloc()分配的内存的结果是没有定义的。c++标准不保证操作员新实现的底层实现使用malloc();事实上,在某些实现上malloc()和new使用不同的堆。检查这个链接

delete() would delete the entire memory space occupied making it imposible to refer the varaiable once its gets deleted where in free() u could still access it.

删除()将删除占用的整个内存空间,使其无法在空闲时()仍然可以访问它时引用varaiable。