码迷,mamicode.com
首页 > 编程语言 > 详细

深入理解c++中的new与delete

时间:2015-09-13 23:09:18      阅读:267      评论:0      收藏:0      [点我收藏+]

标签:

一,new与delete的细节

假如有下面的代码:

string *sp = new string("a value");
string *arr = new string[10];

整个new的语句可以分为三步完成,

首先,编译器使用名为operator new(operator new[])的标准库函数,该函数的作用是分配一块足够大的、原始的空间。第二步,编译器运行相应的构造函数构造对象,第三步,编译器将得到的对象首地址返回。

当在程序中使用 type *p = new type(..)时,编译器按照两条原则寻找对应的operator:

  如果Type是用户自定义类型,优先在类以及父类的成员函数中寻找operator new函数,如果没有,则在全局函数中寻找用户的自定义版本,再没有则使用标准库的版本

  如通用户定义了和标准库一样的函数,不会报重定义

标准库定义了八个可供用户重载在版本,其中nothrow_t定义在头文件new中,用于表示不抛出异常

void *operator new (size_t);
void *operator new[] (size_t);
void operator delete (void *) noexcept;
void operator delete[] (void *) noexcept;

void *operator new (size_t, std::nothrow_t) noexcept;
void *operator new[] (size_t, std::nothrow_t) noexcept;
void operator delete(void*, std::nothrow_t) noexcept;
void operator delete[](void *, std::nothrow_t) noexcept;

用户可以自定义上面的几个函数(注意是自定义,不是重载,参数类型、个数只要满足要求即可,即使与标准库定义的一样也不会报错),这些要求包括:

1, 不能定义这样的new :void *operator new(size_t. void *), 他只能被标准库使用

2,new必须返回void*, 第一个参数必须是size_t,且不能有默认参数

3,delete必须返回void, 第一个参数必须是void *

4,当我们在类中定义operator delete时,若将第二个参数置为size_t, 那该形参的初始值就会变成第一个形参所指物的大小,如果这个类有一个虚析构函数,那么size_t的大小和operator delete的版本将有具体的动态类型决定,虽然我也不太懂,暂且先记下来- -!

 

二、定位new(placement new)

上面提到的operator new()函数会分配空间,虽然我们可以显式调用对象的析构函数,但是却没有办法调用对象的构造函数,此时需要用到一个叫做定位new的函数,该函数只接受一个void *参数,之后会在该指针所指的位置,调用构造函数,构造出一个对象。具体的各种形式如下:

new (place_addr) type;

new (place_addr) type (initilizers);

new(place_addr) type [size];

new(place_addr) type[size] (initilizers);

 

值得注意的是,定位new并不规定这个构造对象的空间是什么空间,可以是标准库的operator new出来的,可以是用户自己的operator new出来的,可以是malloc出来的,甚至可以是栈中的自动变量,如数组- -!,随便是啥都可以。

三、总结

虽然这些东西平时不常用,但是在需要自己精确控制对象的空间分配以及初始化行为时,仅仅从析构函数与构造函数是不够的,这些技术在STL中的内存分配器中就被广泛使用。

 

深入理解c++中的new与delete

标签:

原文地址:http://www.cnblogs.com/64open/p/4782576.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!