分配 | 释放 | 类属 | 能否重载 |
---|---|---|---|
malloc() | free() | C 函数 | 不可 |
new | delete | C++ 表达式 | 不可 |
::operator new() | ::operator delete() | C++ 函数 | 可 |
allocator<T>::allocate() | allocator<T>::deallocate | C++ 标准库 | 可自由设计并予以搭配任何容器 |
void *p1 = malloc(512); // 512 bytes free(p1)
complex<int>* p2 = new complex<int>; // one object delete p2;
void *p3 = ::operator new(512); // 512 bytes ::operator delete(p3);
// 如下使用 C++ 标准库提供的 allocators // 其接口虽有标准规格,但实现厂商并未彻底遵照;下面三种形式略异 #ifdef _MSV_VER // 如下两个函数都是 no-static, 要经过 object 调用。 // 分配 3 个 ints int *p4 = allocator<int>().allocate(3, (int*)0); // 对应标准库分配器的第二个参数 allocator<int>().deallocate(p4, 3); #endif #ifdef __BORLANDC__ // 如下两个函数都是 no-static, 要经过 object 调用。 // 分配 5 个 ints int *p4 = allocator<int>().allocate(5); // 一样包含第二个参数,但声明处有默认值,所以调用处可不写 allocator<int>().deallocate(p4, 5); #endif #ifdef __GNUC__ // 早期版本的实现, 2.9 // 如下两个啊含糊都是 static, 可经过全名调用。 // 分配 512 bytes void *p4 = alloc::allocate(512); alloc::deallocate(p4, 512); #endif
#ifdef __GNUC__ // 现代版本的实现, 4.9 // 如下两个函数都是 no-static,要经过 object 调用。 // 分配 7 个 ints void *p4 = allocator<int>().allocate(7); allocator<int>().deallocate((int*)p4, 7); // 如下两个函数都是 no-static,要经过 object 调用。 // 分配 9 个 ints void *p4 = __gnu_cxx::pool_alloc<int>().allocate(9); __gnu_cxx::pool_alloc<int>.deallocate((int*)p4, 9); #endif
Complex *pc = new Complex(1, 2); 编译器转换为 ==>> Complex *pc; try { /* 1 */ void mem = operator new (sizeof(Complex)); // allocate 申请内存空间 /* 2 */ pc = static_cast<Complex*>(mem); // cast 类型转换 /* 3 */ pc->Complex::Complex(1, 2); // construct 调用构造函数 // 注意:只有编译器才能够像上面那样直接呼叫 ctor } catch (std::bad_alloc) { // 若 allocation 失败,就不执行 constructor }
注:
new 作两个动做ios
申请内存
调用构造函数
new(p)Complex(1, 2)
// ...\vc98\crt\src\newop2.cpp (其中一个实现版本) void *operator(size_t size, const std::nothrow_t &_THROW0()) { // try to allocate size bytes void *p; while ((p = malloc(size)) == 0) { // buy more memory or return null pointer __TRY_BEGIN if (_callnewh(size) == 0) break; _CATCH(std::bad_alloc) return (0); _CATCH_END } }
注:
struct std::nothrow_t{}
)typedef void (*new_handler)(); new_handler set_new_handler(new_handler p) throw()
设置的函数,使得咱们有机会释放掉咱们认为能够释放的内存空间Complex *pc = new Complex(1, 2); delete pc; 编译器转换为 ==>> pc->~Complex(); // 调用析构函数 operator delete (pc); // 释放内存
注:delete 的两个动做
调用析构函数
释放内存
// ...\vc98\crt\src\delop.cpp (其中一个实现版本) void __cdelc operator delete(void *p) __THROW0() { // free an allocated object free(p); }
#include <iostream> using namespace std; class A { public: int id; A() : id(0) { cout << "default ctor. this=" << this << " id=" << id << endl; } A(int i) : id(i) { cout << "ctor. this=" << this << " id=" << id << endl; } ~A() { cout << "dtor. this=" << this << " id=" << id << endl; } }; void test_1() { cout << endl << "test_1" << endl; A *pA = new A(1); cout << pA->id << endl; delete pA; } // simulate new void test_2() { cout << endl << "test_2" << endl; void *p = ::operator new(sizeof(A)); cout << "p=" << p << endl; A *pA = static_cast<A*>(p); cout << pA->id << endl; pA->~A(); ::operator delete(pA); } void test_3() { cout << endl << "test_3" << endl; A *pA = new A(3); cout << pA->id << endl; // pA->A::A(3); // [Error] cannot call constructor 'A::A' directly // A::A(5); // [Error] cannot call constructor 'A::A' directly pA->~A(); // 编译无错误, 析构函数被调用 delete pA; } int main() { test_1(); test_2(); test_3(); return 0; }
输出:[编译器 gnu 4.9,2]express
test_1 // 构造、析构函数被调用,一切正常 ctor. this=0x781510 id=1 1 dtor. this=0x781510 id=1 test_2 // 构造函数未被调用 p=0x781510 7870992 // id 为内存中的随机值 dtor. this=0x781510 id=7870992 // 析构函数可被直接调用,但存在风险!! test_3 ctor. this=0x781510 id=3 // 构造函数被调用 3 dtor. this=0x781510 id=3 // 析构函数被直接调用,但存在风险!! dtor. this=0x781510 id=3 // 析构函数被 delete 时调用
注: