- 最近在和朋友讨论一些技术的时候,提到了placemen new来提高内存一次性申请终身适用的高效问题。所以趁这个机会给大家顺利下几个new相关的技术。
直接上代码里面有讲解
// C++new运算符.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include
using namespace std;
#define operator_new_delete 0
#define placement_new 1
/* 技术要点
* ★★★ new运算符和operator new之间的区别
* 1. new: 指我们在C++里通常用到的关键字。比如 A *a=new A,为了实现这一目的,应用程序需要重载new运算符和delete运算符以控制内存分配的过程。
* 对于new来说,有new和::new之分,前者位于std命名空间中;
* 2. operator new: 是一个标准库函数,并不是运算符。对于operator new 来说,分为全局重载和类重载。
* 事实上系统默认的全局重载也只是调用malloc分配内存,并且返回一个void* 指针;
*
* ★★★ new运算符和operator new之间的联系
* 1. MyClass* p1 = new MyClass; 这行代码实际执行三步操作:
* 1.1 new表达式调用一个名为operator new(或者operator new[])的标准库函数。该函数分配一块足够大的、原始的、未命名的内存空间以便存储A类型的对象(或者对象数组);
* 1.2 编译器运行相应地构造函数以构造这些对象,并为其传入初始值;
* 1.3 对象被分配了空间并构造完成,返回一个指向该对象的指针;
* 如果类MyClass重载了operator new,那么将调用MyClass::operator new(size_t size),如果没有重载,就调用全局函数::operator new(size_t size),全局new操作符由c++默认提供
*
* 2. operator new接口和operator delete接口
* 2.1 标准库定义了以下8个版本。其中前4个版本可能抛出bad_alloc异常,后4个版本不会抛出异常;
* 这些版本可能抛出异常
*
* 第一种分配size个字节的存储空间,并将对象类型进行内存对齐。如果成功,返回一个非空的指针指向首地址。失败抛出bad_alloc异常
* void* operator new (size_t);
* void* operator new[] (size_t);
* void* operator delete (void*) noexcept;
* void* operator delete[] (void*) noexcept;
*
* 第二种在分配失败时不抛出异常,它返回一个NULL指针
* void* operator new (size_t, nothrow_t&) noexcept;
* void* operator new[] (size_t, nothrow_t&) noexcept;
* void* operator delete (void*, nothrow_t&) noexcept;
* void* operator delete[] (void*,nothrow_t&) noexcept;
*
* 第三种是placement new版本,它本质上是对operator new的重载,定义于#include 中。它不分配内存,调用合适的构造函数在ptr所指的地方构造一个对象,之后返回实参指针ptr
* void* operator new (std::size_t size, void* ptr) throw();
*
* 第一、第二个版本可以被用户重载,定义自己的版本,第三种placement new(定位new)不可重载
* MyClass* pMc = new MyClass; //调用第一种
* MyClass* pMc = new(std::nothrow) MyClass; //调用第二种
* new (ptr)MyClass(); //调用第三种
* new (ptr)MyClass()调用placement new之后,还会在ptr上调用MyClass::MyClass(),这里的ptr可以是堆中动态分配的内存,也可以是栈中缓冲
* 对于operator new函数:要实现不同的内存分配行为,应该重载operator new,而不是new
* 2.2 如果我们想要继续使用默认的operator new,就应该写成::new ,字面意思是调用最外层命名空间中的operator new。
* 值得一提的是,全局operator new也是可以被重载的。通过这种方式,我们可以改变所有new的部分行为
*
* ★★★ new和delete是否需要一定成对使用???
* 1. 基础类型:
* 可以不用成对
* 2. 自定义类型:
* 需要成对
*
* ★★★ placemen new定位new表达式
* 1. 功能:
* 定位new允许我们在一个特定的、预先分配的内存地址上构造对象,实参不局限于动态内存
* 2. 形式:
* new ( place_address ) type
* new ( place_address ) type (initializers)
* new ( place_address ) type [size]
* new ( place_address ) type [size] { braced initializer list }
* 其中place_address必须是一个指针,同时在initializers中提供了一个(可能为空的)以逗号分隔的初始值列表,该初始值列表将用于构造新分配的对象
*3. 当仅通过一个地址值调用时,定位new使用operator new(size_t)分配的内存。这是一个我们无法重载的operator new版本。该函数不分配任何内存,它只是简单地返回指针实参;
* 然后由new表达式负责在指定的地址初始化对象以完成整个工作
* eg.
* MyClass* ptr = MyClass char[10]; //allocate memory
* MyClass* pMc = new(ptr)MyClass; //construct in allocated storage ("place")
* pMc->~T(); //destruct
* delete[] ptr; //deallocate memory
*
* ★★★ operator newdelete重载形式
* 1. 成员函数
* 1.1 void* className::operator new( size_t size );
* 1.2 void className::operator delete( void *ptr);
* 1.3 void* className::operator new[](size_t size);
* 1.4 void className::operator delete[](void* ptr);
*
* 2. 全局函数
* 1.1 void* operator new( size_t size );
* 2.2 void operator delete( void *ptr);
* 2.3 void* operator new[](size_t size);
* 2.4 void operator delete[](void* ptr);
*
* 3. 构造析构顺序
* 3.1 new对象
* operator new ---> constructor
* 3.2 delete对象
* destructor ---> operator delete
*
* 在重载 new 或 new[] 时,无论是作为成员函数还是作为全局函数,它的第一个参数必须是 size_t 类型。
* size_t 表示的是要分配空间的大小,对于 new[] 的重载函数而言,size_t 则表示所需要分配的所有空间的总和
* size_t 在头文件 中被定义为typedef unsigned int size_t;,也就是无符号整型
* 当然,重载函数也可以有其他参数,但都必须有默认值,并且第一个参数的类型必须是 size_t
* 如果类中没有定义 new 和 delete 的重载函数,那么会自动调用内建的 new 和 delete 运算符
*/
// 基类
class MyClass
{
public:
MyClass() { m_nSize = 2; cout show();
// 堆空间
char* pBuff = new char[10 * sizeof(MyClass)];
cout show();
p4->~MyClass();
delete[]pBuff;
#endif
system("pause");
return 0;
}
new和delete是否需要成对使用,具体看操作的数据类型
- 因为new[]会创建一个数组,一个对象数组需要一定的空间大小,假设一个对象需要N字节大小,K个对象的数组就需要K*N个空间来构造对象数组,但是在delete[]时候,如何知道数组的长度呢?
- 所以new[]会在KN个空间的基础上,头部多申请4个字节,用于存储数组长度,这样delete[]时候才知道对象数组的大小,才会相应调用K次析构函数,并且释放KN+4大小的内存。
- 2. 自定义数据类型则需要成对使用,否则报错。
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.e1idc.net