C++ new/new operator、operator new、placement new初识

简要释义

1.operator new是内存分配函数(同malloc),C++在全局作用域(global scope)内提供了3份默认的operator new实现,并且用户可以重载operator new。

1 void* operator new(std::size_t) throw(std::bad_alloc);//normal new
2 void* operator new(std::size_t,const std::nothrow_t&) throw();//nothrow new
3 void* operator new(std::size_t,void*) throw();//placement new

下面这两行代码是等价的,都是分配一块大小为sizeof(widget)的内存并返回指针,没有执行构造函数

1 widget *a=(widget*) ::operator new(sizeof(widget));
2 widget *b=(widget*)malloc(sizeof(widget));

2.new/new operator即C++内置的new操作符。

//这里new一个widget对象分成两步
//1.运行期系统调用operator new开辟sizeof(widget)大小的内存
//2.在该内存地址上构造一个widget对象
widget *c=new widget();

我们平常的new操作由运行期系统调用operator new,然后调用构造函数初始化。这个过程是不可重定义的。即程序员不能重载C++内建的new操作符。我们能重载的仅是其中的 operator new/operator new[],即分配内存的部分。

3.placement new是operator new在全局作用域上的一个重载版本,即如上我们看到的

1 void* operator new(std::size_t,void*) throw();//placement new

placement new并不分配内存,而是返回已分配的内存的指针,这个指针正是函数参数列表中的void *,即“返回一个你刚传入的已分配的内存的指针”。

std::中该函数的实现:

1 inline _LIBCPP_INLINE_VISIBILITY void* operator new  (std::size_t, void* __p) _NOEXCEPT {return __p;}

那么为什么需要这个placement new呢?

答案是:当你需要在一段已分配的内存中构造对象时,调用寻常的new widget()会开辟另外一个内存空间,而非在已知地址上构造widget()对象。

//这里先申请了一段内存空间,由指针widget*a持有,并未调用构造函数
//然后用placement new在a地址上构造了widget对象
//这里::表示调用在global scope中的匹配函数
widget *a=(widget*) ::operator new(sizeof(widget));
::new(a) widget();

进一步的讨论

1.placement new实质上是有额外实参之operator new,一般情况下我们指的placement new是那个额外实参为void*的重载版本(已被纳入C++标准程序库),这些叫法对我们的讨论没有影响,只要知道placement new同时也是一种operator new即可。但是不要忘了我们可以重载其它版本的placement new,例如额外实参为std::ostream&,提供log功能。

 1 #include <iostream>
 2 class widget
 3 {
 4 public:
 5     static void * operator new(std::size_t _size,std::ostream& o)
 6     {
 7         o<<"void * operator new(std::size_t _size,ostream& o)"<<std::endl;
 8         return ::operator new(_size);
 9     }
10     widget()
11     {
12         std::cout<<"widget()"<<std::endl;
13     };
14     ~widget()
15     {
16         std::cout<<"~widget()"<<std::endl;
17     };
18
19 };
20 int main()
21 {
22     //下面两种构造方法是等价的
23     //构造一个widget对象,并且使用有log功能的operator new
24     widget* a=(widget*) widget::operator new(sizeof(widget), std::cout);
25     ::new(a) widget();
26
27     //同样构造一个widget对象,并且使用有log功能的operator new
28     widget* b=new(std::cout) widget();
29     return 0;
30 }

这份示例代码中,我在类中重载了placement new,附带的额外参数是ostream&。

2.注意作用域遮掩问题。如果你在类内重载了一个operator new,当你对这个类及其子类使用new操作符的时候,会掩盖全局作用域中的operator new,编译器发现里层作用域(类内)有operator new声明,就不会查找全局作用域是否有其它operator new声明,而是直接进入参数匹配阶段,如果你重载的operator new参数和调用的不匹配,便会抛出一个编译错误。

解决方法就是:如果类内重载了operator new,并且你仍有可能使用到全局作用域中的operator new,请同时也重载和全局作用域同型的operator new,确保调用成功。

为你的类建立一个base class,内含全局作用域同型的operator new,使其调用全局作用域内的operator new即可。

 1 #include <iostream>
 2 class globalScopeNew
 3 {
 4 public:
 5     static void* operator new(std::size_t size) throw(std::bad_alloc)
 6     {
 7         return ::operator new(size);
 8     }
 9     static void* operator new(std::size_t size,const std::nothrow_t& t) throw()
10     {
11         return ::operator new(size, t);
12     }
13     static void* operator new(std::size_t size,void* p) throw()
14     {
15         return ::operator new(size, p);
16     }
17
18 };
19 class widget:public globalScopeNew
20 {
21 public:
22     using globalScopeNew::operator new;
23     static void * operator new(std::size_t _size,std::ostream& o)
24     {
25         o<<"void * operator new(std::size_t _size,ostream& o)"<<std::endl;
26         return ::operator new(_size);
27     }
28     widget()
29     {
30         std::cout<<"widget()"<<std::endl;
31     };
32     ~widget()
33     {
34         std::cout<<"~widget()"<<std::endl;
35     };
36
37 };
38 int main()
39 {
40     widget* w2=new(std::cout) widget();
41     //这句调用原来不能通过编译
42     widget* w1=new widget();
43     widget* w3=(widget*)operator new(sizeof(widget));
44     //这句调用原来不能通过编译
45     new(w3) widget();
46     return 0;
47 }

注意,这边需要在子类中using globalScopeNew::operator new;即在子类中使基类的operator new可见。

这样,各种形式的new操作符调用都能通过编译了。

时间: 2024-12-09 20:30:18

C++ new/new operator、operator new、placement new初识的相关文章

C++ 中 new 操作符内幕:new operator、operator new、placement new

原文链接 一.new 操作符(new operator) 人们有时好像喜欢有益使C++语言的术语难以理解.比方说new操作符(new operator)和operator new的差别. 当你写这种代码: string *ps = new string("Memory Management"); 你使用的new是new操作符. 这个操作符就象sizeof一样是语言内置的.你不能改变它的含义,它的功能总是一样的.它要完毕的功能分成两部分.第一部分是分配足够的内存以便容纳所需类型的对象.

C++中的new、operator new与placement new

转:http://www.cnblogs.com/luxiaoxun/archive/2012/08/10/2631812.html new/delete与operator new/operator delete new operator/delete operator就是new和delete操作符,而operator new/operator delete是函数. new operator 调用operator new分配足够的空间,并调用相关对象的构造函数 不可以被重载 operator n

new 、operator new 和 placement new

一.原生operator new 我们先从原生operator new开始.考虑如下代码,它用来分配5个int型的空间并返回指向他们的指针[1]: int* v = static_cast<int*>(::operator new(5 * sizeof(*v))); 当像如上的调用,operator new扮演原生的内存分配角色,类似malloc.上面等价于: int* v = static_cast<int*>(malloc(5 * sizeof(*v))); 释放用operat

C++中的new,operator new与placement new

以下是C++中的new,operator new与placement new进行了详细的说明介绍,需要的朋友可以过来参考下 new operator/delete operator就是new和delete操作符,而operator new/operator delete是函数. new operator(1)调用operator new分配足够的空间,并调用相关对象的构造函数(2)不可以被重载 operator new(1)只分配所要求的空间,不调用相关对象的构造函数.当无法满足所要求分配的空间

【转】C++易混知识点3. New Operator, Operator New, Placement New 实例分析,比较区别

我们知道,C++中引入了New 这个内置符号,很大方便了指针的使用,程序员不必关注与这块堆上新分配的内存是如何来的,如何初始化的,然后如何转换为我们想要的类型指针的.现在,我们重点来分析下这个NEW内置符号背后的步骤和所调用到的函数.这里面涉及到new operator, operator new, placement new. 转载请注明出处: http://blog.csdn.net/elfprincexu 1. New Operator (__type__ * a = new a();)

小结:c++中的new、operator new和placement new

c++中的new.operator new和placement new 一.new new(也称作new operator),是new 操作符,不可重载 class T{...}; T *t = new T(initial_args_list); //此时的new ,是new 操作符 new操作 会执行以下三个步骤 调用类的(如果重载了的话)或者全局的operator new分配空间 用类型后面列的参数列表来调用构造函数,生成类对象 返回对应的指针 二. operator new operato

new、operator new、placement new

new :操作符 class MyClass {...};    MyClass *p = new MyClass; 分以下三个步骤 1. 调用operator new分配内存 2. 调用构造函数生成类对象 3. 返回相应指针 operator new:分配内存 1.缺省情况下,C++在global作用域内提供以下三种形式的operator new void* operator new(std::size_t)throw(std::bad_alloc);  //正常的operator new,n

[C++空间分配]new运算符、operator new、placement new的区别于联系

先科普一下: 1. new的执行过程: (1)通过operator new申请内存 (2)使用placement new调用构造函数(内置类型忽略此步) (3)返回内存指针 2. new和malloc的比较: (1)new失败时会调用new_handler处理函数,malloc不会,失败时返回NULL (2)new能通过placement new自动调用对象的构造函数,malloc不会 (3)new出来的东西是带类型的,malloc是void*,需要强制转换 (4)new是C++运算符,mall

C++ new operator, delete operator, operator new, operator delete, new placement

http://www.younfor.com/cpp-new-placement-new-operator-new.html http://www.cnblogs.com/luxiaoxun/archive/2012/08/10/2631812.html http://kelvinh.github.io/blog/2014/04/19/research-on-operator-new-and-delete/ new operator 就是C++中定义的关键字new,调用new而触发的行为,del