我经历了new和delete的重载,我在一本书中读到new和malloc之间的区别在于new 调用构造函数,返回调用变量的类型,第三个区别是我们可以逐类重载new ,而malloc不能,有人也可以逐类解释这个类。
4 回答
::operator new
在全局命名空间中可以被替换(覆盖),而不是重载。这会导致使用覆盖而不是标准库提供的函数。并且my_class::operator new
可以提供,因此它将在new my_class
表达式中使用,这也与重载不同。
仅当您使用放置语法时,重载new
才会发挥作用:new
new ( memory_pool, 123, other_args ) my_class( constructor_args )
在关键字之后的括号中提供额外的参数new
会导致调用另一个重载,并在指定需要多少内存operator new
之后附加额外的参数。size_t
你当然可以::malloc
像任何其他函数一样重载,通过定义一个接受不同参数的版本:
void *malloc( std::size_t size, allocation_pool &pool );
这只是一个碰巧被调用的新函数malloc
。但是最好使用明确的std::
限定来调用库函数,并且添加std::malloc
重载将违反库的规则。
你不能换std::malloc
。唯一可以替换的功能是::operator new
. 没有特定于类的东西,malloc
因为它不接受指示哪个类将进入返回的内存块的参数。malloc
不知道你将如何处理返回的内存;它只是一团字节。
作为程序组织的问题,可能应该给出一个更专业的分配器并将其称为另一个名称,而不是malloc
. 如果您需要根据类型调用不同的函数,请使用模板,例如
template< typename allocated >
void *my_allocate( std::size_t sz ); // maybe "sz" param is unnecessary.
您还可以专门std::allocator< my_class >
化及其成员函数allocate
。然后各种标准库工具将调用您的函数,尽管没有自定义new
. new
(由于它的怪癖,您可能会避免过于深入地了解习惯。)
重载new
与constructors
. Aclass
可以提供自己的 operator new()
,它负责在构造函数调用之前分配内存。这对于优化小对象池很有用,例如,您还可以查看 operator 的各种重载new()
,包括所谓的“placement new”,允许为诸如就地构造(用户提供的缓冲区)之类的东西提供任意参数, 文件/线路诊断等
注意:您不能随意“重载”或“覆盖”标准 C 库函数,但通常的做法是允许您覆盖它的合理子集。
一般来说,链接器不知道给定的目标文件是用什么语言编写的,它的工作知识水平要低得多——目标文件的外部符号在所有目标文件和链接在一起的共享库中应该是唯一的因为链接器本身不能随意删除在其命令行上给出的带有重复符号的对象。值得注意的例外是静态库 (.a)——如果它有助于删除重复的外部符号,则允许链接器从存档中删除任何项目或项目。
允许覆盖库函数由两部分组成:
具有将函数标记为可重载的语法的编译器——适当的外部符号将被标记为“弱链接”。铁,对于
gcc
:`__attribute__((weak)) void *malloc(size_t size)`
ld.so
理解弱链接的动态链接器( )。
不知道是否malloc()
在特定 shared 中声明为弱符号libc
,但通常是这样,因此您很有可能能够覆盖它,但您的里程可能会有所不同。
是的,我们可以重载标准库函数 malloc。请看下面的代码片段:
#include <iostream>
void malloc(void)
{
puts("malloc");
}
int main()
{
int *p= (int*)malloc(8);
malloc();
free(p);
return 0;
}
此代码打印malloc。
此外,以下是该程序内存的 TEXT 部分的片段:
0000000000400744 T _Z6mallocv
0000000000400770 T main
以下是 DYNAMIC SYMBOL TABLE 的片段
0000000000000000 DF *UND* 00000000000001d2 GLIBC_2.2.5 malloc
0000000000000000 DF *UND* 00000000000001a5 GLIBC_2.2.5 __libc_start_main
因此,我们可以重载标准库函数,如 c++ 中的 malloc。