New

今天,我们只讲new。

 

1. new operator

new操作符(new operator)比较容易理解,相信对C++比较熟悉的人,对下面的代码都不会觉得陌生。这是使用new 最常见的形式。
class A{
....
};
std::shared_ptr<A> a(new A);
new operator实际上就是: 分配内存+调用构造函数初始化。

 

2. operator new
new operator和operator new虽然差不多,但是你不可以把它们等同起来。与new operator相比,operator new 少了构造初始化的部分,它与malloc比较像。
operator new的声明一般为:
void * operator new(size_t size);
需要注意的是,operator new返回一个未经过处理的指针(类型是void*)。new operator调用operator new来分配内存,operator new也能够被重载。
默认的operator new 重载版本有:
void * operator new(std::size_t count) throw(std::bad_alloc); //normal new
void * operator new(std::size_t count, void *ptr)throw(); //placement new
void * operator new(std::size_t count, const std::nothrow_t&)throw();//nothrow new, 为了兼容以前的版本
我们来看一下operator new的源码:
void* operator new(std::size_t) _GLIBCXX_THROW (std::bad_alloc)
__attribute__((__externally_visible__));
void* operator new[](std::size_t) _GLIBCXX_THROW (std::bad_alloc)
__attribute__((__externally_visible__));
  •  _GLIBCXX_THROW: 指定该函数抛出的异常,C++11后该宏为空
  • __attribute__: GCC使用__attribute__关键字来描述函数,变量和数据类型的属性,用于编译器对源代码的优化。
  • __externally_visible__: GCC的优化参数,详情:https://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Function-Attributes.html
 
3. placement new
所谓定位放置(placement new)就是在用户指定的内存位置上构建新的对象,这个构建过程不需要额外分配内存,只需要调用对象的构造函数即可。
class A{
....
};
int main(){
char mem[100];
A* p=new (mem) A;
p->~A();
return 0;
}
operator new和placement new的关系:
class A{
....
};

A* p=new A(10);//有参构造
//等同于下面的调用
void* mem=malloc(sizeof(A));
A* p=new (mem) A(10);
看似神奇的placement new实际上是operator new的一个全局重载版本,它实际上做了这么一件事(我们来看一下源码):
// Default placement versions of operator new.
inline void* operator new(std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT
{ return __p; }
inline void* operator new[](std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT
{ return __p; }

 我们可以看到实际上它不加任何处理直接返回了指针。那么函数的两个参数从哪来?

其实,当我们写了下面的代码时:
A* p=new (mem) A;
实际上,转变为了:
operator new (sizeof(A), men);
到这里,就知道上面源码的operator new两个参数是什么了吧。

 

4. 重写operator new
这部分省略(网上的资料有不少):
https://www.cnblogs.com/cly-blog/p/5984660.html

 

5. 总结
看到这里,你是否对new operator、operator new、placement new有了一个全面的了解,下面我们来总结一下:
  • new operator:分配内存+调用构造函数
  • operator new:分配内存
  • placement new:在已分配的内存里调用构造函数
  • 假设你想定制自己的在堆对象被建立时的内存分配过程,你应该写你自己的operator new函数。然后使用new操作符,new操作符会调用你定制的operator new。

 
生命中所有的灿烂,终要寂寞偿还。——《百年孤独》
posted @ 2019-09-11 23:59  ZWJBLOG  阅读(230)  评论(0编辑  收藏  举报