-
参考
-
普通的
newnew是C++里很常用的操作符号,比如说创建一个对象A* = new A();,这个操作回执行下面3个步骤- 调用
operator new分配内存,operator new(sizeof(A)),需要注意的是new是一个操作符号,operator new是一个函数,前者不能重载,后者能 - 调用构造函数
A::A();,进行初始化 - 返回内存首地址
- 调用
- 然后上面说到,
operator new是能重载的,如果没有去重载,调用的则是C++提供的默认的operator new(size_t),如果想下面代码一样重载了 - 那么,在创建
TestNew时就要这样TestNew* pTestNew = new("hahaha", 1) TestNew();,在new后填上参数,然后就会去执行重载后的operator new函数
class TestNew : public TestBase { public: TestNew(); ~TestNew(); void Test(); void* operator new (size_t size, const char* msg, int ret); void operator delete(void* pointer); } void* TestNew::operator new (size_t size, const char* msg, int ret) { std::cout << "operator new size " << size << " with string " << msg << " ret " << ret << std::endl; return ::operator new(size); } void TestNew::operator delete(void* pointer) { std::cout << "operator delete" << std::endl; ::operator delete(pointer); }- 然后
operator new有三种形式- 第一种,
void* operator new (std::size_t size) throw (std::bad_alloc);,默认的,成功时返回对象内存地址,失败时抛异常 - 第二种,
void* operator new (std::size_t size, const std::nothrow_t& nothrow_constant) throw();,失败时不抛异常 - 第三种,
void* operator new (std::size_t size, void* ptr) throw();,这个就是下面说的placement new,这种不能重载
- 第一种,
- 同理,
operator delete也一样
-
placement new
- 系统内存分配的速度其实相对来说是不快的,特别是内存中碎片很多,此时又需要申请一块大内存时,就会更慢,所以如果是需要频繁申请内存的场景下,就可以使用
placement new了。 - 其原理就是在已申请的内存上创建对象,因为少了申请内存的操作(因为提前申请好了),所以效率会高些。
- 使用时,需要传入内存的首地址,
Test* pTest = new (buff)Test; - 这个内存地址可以是堆里的,也可以是栈里的
- 使用上面的方法创建对象时,并不会申请一块新内存,而是在传入的内存地址处创建对象,然后调用对应的构造函数,然后释放时,需要显式调用析构函数
- 这种方式比较适合用于需要频繁申请内存对象的场合,比如接收消息,每次收到客户端发过来的消息,需要申请一块内存去处理,用完后又需要将其释放,如果使用普通的申请方式,就会导致申请次数很多,而且容易产生内存碎片,所以可以使用
placement new的方式,将申请内存的操作省去,直接复用内存,做对象的构造和析构即可
class Test { public: Test() {} ~Test() {} int GetId() { return m_nId; } void SetId(int nId) { m_nId = nId; } private: int m_nId; } void DoTest() { char* pBuff = new char[sizeof(Test)]; Test* pTest = new (buff)Test; pTest->SetId(1); pTest->~Test(); delete []buff; } - 系统内存分配的速度其实相对来说是不快的,特别是内存中碎片很多,此时又需要申请一块大内存时,就会更慢,所以如果是需要频繁申请内存的场景下,就可以使用