2012-03-22 59 views
2

今天我正在为我的代码写一个小小的Memory Profiler,并且第一次超载了operator new。在这样做的时候,我认为语法是void* operator new(size_t sz)。这的确与malloc非常相似,您有void* malloc(size_t sz)void *在malloc与运算符new

这让我陷入思考,因为当你使用malloc,你需要明确转换指针回到你的数据类型,而新的,你不需要这么做。编译器如何找出new的正确数据类型,以及为什么使其返回void *?是不是T* operator new(size_t sz)更直观?

+3

在C中,您不必强制转换'malloc()'的返回值。实际上,投射最多是多余的,并且可能隐藏编译器在没有演员时会遇到的错误。 – pmg 2012-03-22 23:38:48

+0

@pmg,冷静下来,这个问题不应该真的被标记为'C' – Shahbaz 2012-03-22 23:42:15

+0

记住'免费'分配的数据'新' – 2012-03-22 23:43:28

回答

5

C++分离内存分配和对象构造。分配功能(即,operator new())将void *返回给一些存储器,并且运算器在该存储器中构造对象。如果你愿意,在操作者new“转换”存储器为对象,和以展示位置new表达是有点像“演员”:

void * addr = ::operator new(sizeof(Foo)); // memory 

Foo * p = ::new (addr) Foo(1, true, 'a');  // object (note: no cast!) 

p->~Foo();         // it's almost over 

::operator delete(addr);      // now it's over! 

默认的new执行分配和施工非配置形式一气呵成。这在道德上等同于这个例子的前半部分。但是,分配和建设仍然是两个截然不同的概念。

+0

您能否介绍一下“operator new()'”和“new'运算符”之间的区别。这两件事是不同的吗?另外,第二行,'Foo * p = :: new(addr)Foo(1,true,'a');',是什么意思? – GradGuy 2012-03-22 23:44:30

+0

是的,他们不一样。第一个是功能。第二种是构成“新”表达式的语言结构。 new表达式的值是一个指向新构造对象的指针。示例的第一行调用分配函数;第二个涉及“新”表达式(以放置形式)。只有当你编写一个默认的新表达式时,分配函数才会被自动调用,而分配函数是唯一允许你替换的东西(或者每个类的重载)。 – 2012-03-22 23:45:34

+0

谢谢。我没有意识到这一点:) – GradGuy 2012-03-22 23:48:01

7

operator new函数不会返回T*,因为返回值不指向T,而是指向任意垃圾。直到调用构造函数,你才有一个指向类实例的指针。

+0

我想补充一点,operator new函数实际上调用了构造函数,注册了析构函数以便删除时间,并且如果要执行自己的内存管理,则可以重载所有的函数(即for垃圾回收) – 2012-03-23 00:38:06

1

operator new与新运营商之间有所不同。后者创建给定类型的对象,前者仅分配内存。新操作员为所创建的类型调用operator new,或者,如果没有为所需类型定义版本,则使用全局operator new。您不能从operator new函数返回T*,因为它将指向尚未创建的对象。该对象只在构造函数运行后才创建(以及任何内部维护,例如vtable创建,RTTI信息等)。

不要忘记,你可以覆盖任何类的operator new并改变它的行为 - 它不需要实际分配任何内存,它只需要返回一个指向内存的指针。例如,该内存可以来自预分配的块。

1

operator newnew运算符的用户可覆盖的运行时支持函数,它只提供分配适当对齐和大小的内存块的服务。该功能不是运营商本身的new;当您覆盖此函数时,您不会重写new运算符本身,而只会替换分配服务。如果需要,new运算符可以被认为是一个语法糖,它编译成对其帮助程序operator new的调用,以获取内存,以及构造函数调用来初始化它。