全局非抛出的::operator new和std::malloc之间的区别

34

C++有几个函数可用于获取动态存储,其中大部分在某些基本方面略有不同。通常操作系统还会添加一些其他的函数。

由于其可移植性和相似性,其中有两个函数特别引人注目:malloc::operator new

全局的void* operator new(size_t, ::std::nothrow&)void* malloc(size_t)这两个函数在标准和实现方面是否存在差异?

由于似乎有些混淆我所说的内容,请考虑以下两个调用:

void* p = ::std::malloc(10);
void* q = ::operator new(10, ::std::nothrow);

显而易见的区别是如何释放内存:

::std::free(p);
::operator delete(q);

注意:此问题不是例如new/delete和malloc/free之间的区别是什么?这样的重复问题,因为它涉及使用实际上不执行任何构造函数调用的全局operator new

3个回答

30

除了语法和freedelete之外,主要区别如下:

  1. 您可以可移植地替换::operator new
  2. malloc附带有realloc,而new没有相应的功能;
  3. new具有new_handler的概念,而malloc没有相应的功能。

(替换malloc会开启一个无底洞。虽然可以完成此操作,但不可移植,因为它需要了解链接器的知识。)


哦,像那样替换::operator new真是相当有趣。 - danielschemmel
1
一些研究表明,C++03已经包含了new_handler的概念(§18.4.2),只是在C++11中进行了扩展。 - danielschemmel
@gha.st:你说得对,C++11只引入了get_new_handler。已修复。 - Fred Foo
1
(4) malloc报告失败时返回空指针结果,operator new通过异常报告失败。(5) 用户代码直接调用malloc,而通常通过类似事务的new表达式间接调用operator new来进行分配和初始化。 - Cheers and hth. - Alf
1
问题是关于非抛出式的 new - Fred Foo
显示剩余2条评论

6
我能想到两个区别:
  1. 在释放内存时必须使用哪个函数,operator delete vs. free()

  2. C++程序可以合法地提供自己的版本::operator new,并且这个版本保证会被new表达式调用。但是无法用自己的版本覆盖malloc


据我所知,malloc是一个弱符号,这意味着您可以覆盖它。 - Zaffy
1
@Zaffy 这完全取决于实现(编译器和标准库,还有链接器在这种情况下)。就标准、可移植的 C++ 而言,这是不可能的。 - Angew is no longer proud of SO

1
我可以在不做更多研究的情况下看到的宏观差异是,全局::new运算符的抛出变体如果无法进行分配,则会抛出std::bad_alloc,而malloc则返回NULL。但我相信这里列出的大部分差异都适用于全局::new运算符,即使主题是关于new的。

3
请看一下新版本的代码,其中第二个参数采用了::std::nothrow& - danielschemmel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接