我知道它们在语法上是如何不同的,并且C ++使用new,而C使用malloc。但他们是如何工作的,在一个高级别的解释中?
请参阅What is the difference between new/delete and malloc/free?
答案 0 :(得分:9)
我将引导您回答这个问题:What is the difference between new/delete and malloc/free?。马丁提供了很好的概述。快速了解他们如何工作(不要深入了解如何将其作为成员函数重载):
样品:
new (a, b, c) TypeId;
// the function called by the compiler has to have the following signature:
operator new(std::size_t size, TypeOfA a, TypeOfB b, TypeOf C c);
new_handler
,并希望它可以生成。如果仍然没有足够的位置,则必须抛出std::bad_alloc
或从中派生。一个具有throw()
(无抛出保证)的分配器,在这种情况下它将返回一个空指针。 有一些特殊名称的特殊分配函数:
no-throw
新的。这需要nothrow_t
作为第二个参数。如下所示的表单的新表达式将调用仅使用std :: size_t和nothrow_t的分配函数:示例:
new (std::nothrow) TypeId;
placement new
。这将void *指针作为第一个参数,而不是返回新分配的内存地址,它返回该参数。它用于在给定地址创建对象。标准容器使用它来预分配空间,但稍后只在需要时创建对象。代码:
// the following function is defined implicitly in the standard library
void * operator(std::size_t size, void * ptr) throw() {
return ptr;
}
如果分配函数返回存储,并且运行时创建的对象的构造函数抛出,则自动调用operator delete。如果使用新形式的其他参数,例如
new (a, b, c) TypeId;
然后调用带有这些参数的运算符delete。只有在删除完成时才调用该运算符删除版本,因为对象的构造函数确实抛出了。如果你自己调用delete,那么编译器将使用普通的operator delete函数只占用void*
指针:
int * a = new int;
=> void * operator new(std::size_t size) throw(std::bad_alloc);
delete a;
=> void operator delete(void * ptr) throw();
TypeWhosCtorThrows * a = new ("argument") TypeWhosCtorThrows;
=> void * operator new(std::size_t size, char const* arg1) throw(std::bad_alloc);
=> void operator delete(void * ptr, char const* arg1) throw();
TypeWhosCtorDoesntThrow * a = new ("argument") TypeWhosCtorDoesntThrow;
=> void * operator new(std::size_t size, char const* arg1) throw(std::bad_alloc);
delete a;
=> void operator delete(void * ptr) throw();
如果你这样做
new (possible_arguments) TypeId[N];
编译器使用operator new[]
函数而不是普通operator new
。操作符可以传递第一个不完全是sizeof(TypeId)*N
的参数:编译器可以添加一些空间来存储创建的对象数(为了能够调用析构函数而需要)。标准就是这样说的:
new T[5]
会调用运营商new[](sizeof(T)*5+x)
和new(2,f) T[5]
会调用运营商new[](sizeof(T)*5+y,2,f)
。答案 1 :(得分:2)
new
与malloc
的不同之处如下:
operator new
在已分配的内存中构造一个值。可以通过重载此运算符来调整此行为,适用于所有类型,或仅适用于您的类。总而言之,new
是高度可定制的,除了内存分配之外还可以进行初始化工作。这是两个很大的不同。
答案 2 :(得分:1)
虽然malloc
/ free
和new
/ delete
具有不同的行为,但它们在低级别执行相同的操作:管理动态分配的内存。我假设这是你真正要问的。在我的系统上,new
实际上在内部调用了malloc
来执行其分配,所以我只会谈谈malloc
。
malloc
和free
的实际实现可能会有很大差异,因为有很多方法可以实现内存分配。一些方法获得更好的性能,一些方法浪费更少的内存,另一些方法更好地进垃圾收集语言也可能有完全不同的分配方式,但您的问题是关于C / C ++。
通常,块是从堆中分配的,即程序地址空间中的大面积内存。该库为您管理堆,通常使用sbrk
或mmap
等系统调用。从堆分配块的一种方法是维护存储块大小和位置的空闲和分配块的列表。最初,列表可能包含整个堆的一个大块。当请求新块时,分配器将从列表中选择一个空闲块。如果块太大,它可以分成两个块(一个是所请求的大小,另一个是剩下的大小)。当释放分配的块时,它可以与相邻的空闲块合并,因为有一个大的空闲块比几个小的空闲块更有用。实际的块列表可以存储为单独的数据结构或嵌入到堆中。
有很多变化。您可能希望保留单独的空闲和已分配块列表。如果对于常见大小的块具有堆的单独区域,或者对于这些大小的单独列表,则可能会获得更好的性能。例如,当您分配一个16字节的块时,分配器可能有一个特殊的16字节块列表,因此分配可以是O(1)。仅处理2的幂的块大小(其他任何东西被四舍五入)也可能是有利的。例如,Buddy allocator以这种方式工作。
答案 3 :(得分:0)
“new”比malloc做得更多。 malloc只是分配内存 - 它甚至不会为你归零。新的初始化对象,调用构造函数等。我怀疑在大多数实现中,new只不过是基于malloc的基本类型的薄包装。
答案 4 :(得分:0)
在C中: malloc分配一个你在参数中提供的大小的内存块,并返回一个指向这个内存的指针。
内存在堆上声明,因此请确保在完成后释放它。