目录
前言
侯捷老师内存管理视频的讲解的C++内存分配的每一层面如下:
四个层面的基本用法
(1)malloc / free
malloc / free 申请(释放)内存的语法比较简单
void* p1 = malloc(512); // 分配512 bytes
if (p1 != nullptr)
cout << "malloc allocate successfully!" << endl;
// int* p = (int*)malloc(sizeof(int)*128); // 分配128个int型空间
free(p1);
p1 = nullptr;
(2)new / delete
new / delete 在堆区开辟空间(释放),注意其内部调用的依然是 malloc / free
complex<int> * p2 = new complex<int>; // 申请创建one object
if (p2 != nullptr)
cout << "new allocate successfully!" << endl;
delete p2;
p2 = nullptr;
(3)operator new / operator delete
operator new / operator delete函数可以进行重载,若使用的是全局的,需要加上作用域 ::,其内部调用的依然是 malloc / free
void* p3 = ::operator new(512); //512 bytes
if (p3 != nullptr)
cout << "::operator new allocate successfully!" << endl;
::operator delete(p3);
p3 = nullptr;
(4)C++ 标准库提供的 allocators
其接口虽有标准规格,但实现厂商并未完全遵守;下面三者形式略异。
#ifdef _MSC_VER
//以下两函数都是 non-static,一定要通过 object 调用。以下分配 3 个 ints.
int* p4 = allocator<int>().allocate(3, (int*)0);
if (p4 != nullptr)
cout << "allocator<int>() allocate successfully!" << endl;
allocator<int>().deallocate(p4, 3);
#endif
#ifdef __BORLANDC__
//以下两函数都是 non-static,一定要通过 object 调用以下分配 5 个 ints.
int* p4 = allocator<int>().allocate(5);
allocator<int>().deallocate(p4, 5);
#endif
#ifdef __GNUC__
//以下两函数都是 static,可通过全名调用之。以下分配 512 bytes.
//void* p4 = alloc::allocate(512);
//alloc::deallocate(p4,512);
//以下两函数都是 non-static,一定要通过 object 调用以下分配 7 个 ints.
void* p4 = allocator<int>().allocate(7);
allocator<int>().deallocate((int*)p4, 7);
//以下两函数都是 non-static,一定要通过 object 调用以下分配 9 个 ints.
void* p5 = __gnu_cxx::__pool_alloc<int>().allocate(9);
__gnu_cxx::__pool_alloc<int>().deallocate((int*)p5, 9);
#endif
输出结果
new / delete expression
C++中代用new在堆区创建对象,其实经历了以下步骤:1. 开辟空间;2. 类型转换;3. 调用构造函数;4 指针指向创建的对象。 同样地,delete释放对象的步骤:1. 调用析构函数;2 释放内存。
#include<iostream>
class A
{
public:
A(int Id = 0):id(Id)
{
std::cout << "ctor.this = " << this << " id = " <<id << std::endl;
}
~A(){std::cout << "dtor.this=" << this << " id=" << id << std::endl; }
public:
int id;
};
int main()
{
// 正常创建一个类对象
A* p = new A(1);
std::cout <<"p->id = "<< p->id << std::endl; // id = 1
// p->A::A(3); // in VC6可以通过调用ctor;in GCC 错误,不能调用ctor
delete p;
std::cout << std::endl;
//simulate: A* p = new A(2)
void* mem = ::operator new(sizeof(A)); // 1 allocate
std::cout << "mem =" << mem << std::endl;
p = static_cast<A*>(mem); // 2 cast
std::cout << "p = "<< p << std::endl;
p->A::A(2); // 3 调用construct,并指向该对象
std::cout << std::endl;
//simulate delete p
p->~A(); // 1 调用析构函数
::operator delete(p); // 2 释放内存
system("pause");
return 0;
}
在simulate A* p = new A(2)
和delete p
的过程中,我们使用了::operator new
和 ::operator delete
这里因为这两个是可以重载的,我们使用::
表示我们使用的是全局的,也就是系统给我们提供的原始operator new、operator delete
。
输出结果
这里 构造函数 不可以被直接调用,例如在 p->A::A(3); // in VC6可以通过调用ctor;in GCC 错误,不能调用ctor
,而 p->~A();
却可以直接调用。