[侯捷C++](内存管理)

[侯捷C++](内存管理),第1张

[侯捷C++](内存管理)

文章目录

第一讲:primitives

四种内存分配与释放基本构件之 new/delete expression

1、内存申请2、内存释放3、模拟编译器直接调用构造和析构函数 Array new 第二讲:malloc/free第三讲:std::allocator第四讲:other allocators第五讲:loki::allocator


第一讲:primitives 四种内存分配与释放


在编程时可以通过上图的几种方法直接或间接地 *** 作内存。下面将介绍四种C++内存 *** 作方法:

1.::operator new()调用malloc,::operator delete()调用free

2.通常可以使用malloc和new来分配内存,当然也可以使用::operator new()(是一个全局函数)和分配器allocator来 *** 作内存,下面将具体介绍这些函数的使用方法。对于不同的编译器,其allocate函数的接口也有所不同:

对于GNU C,不同版本又有所不同:

这张图中的__gnu_cxx::__pool_alloc().allocate()对应于上张图中的allocator().allocate()。

通过malloc和new分配内存、通过free和delete释放内存是十分常用的,通过::operator new *** 作内存比较少见,allocator分配器 *** 作内存在STL源码中使用较多,对于不同的编译环境使用也有所不同。下面这个例子是基与VS2019环境做测试的

#include 
#include 
#include //std::allocator

using namespace std;
namespace jj01
{
	void test_primitives1()
	{
		cout << "ntest_primitives().......... n";
		void* p1 = malloc(512);//512 bytes
		free(p1);

		complex* p2 = new complex;//one object一个单元
		delete p2;

		void* p3 = ::operator new(512);//512 bytes
		::operator delete(p3);

		//以下使用 C++ 標準庫提供的 allocators。
		//其接口雖有標準規格,但實現廠商並未完全遵守;下面三者形式略異。
#ifdef _MSC_VER
		//VC接口
		//以下兩函數都是 non-static,定要通過 object 調用。以下分配 3 個 ints.
		//allocator()临时对象
		int* p4 = allocator().allocate(3, (int*)0);
		p4[0] = 666;
		p4[1] = 999;
		p4[2] = 888;
		cout << "p4[0] = " << p4[0] << endl;
		cout << "p4[1] = " << p4[1] << endl;
		cout << "p4[2] = " << p4[2] << endl;
		//还内存的时候还要把当初分配内存大小表明,这种事情只有容器可以做到
		allocator().deallocate(p4, 3);
#endif // _MSC_VER

	}
}

int main(void)
{
	jj01::test_primitives1();
	return 0;
}
test_primitives()..........
p4[0] = 666
p4[1] = 999
p4[2] = 888

可见 int* p4 = allocator().allocate(3, (int*)0) *** 作成功申请了三个int的空间。

基本构件之 new/delete expression 1、内存申请


上面这张图揭示了new *** 作背后编译器做的事:

1、第一步通过operator new() *** 作分配一个目标类型的内存大小,这里是Complex的大小;
2、第二步通过static_cast 将得到的内存块强制转换为目标类型指针,这里是Complex*
3、第三版调用目标类型的构造方法,但是需要注意的是,直接通过pc->Complex::Complex(1, 2)这样的方法调用构造函数只有编译器可以做,用户这样做将产生错误。

值得注意的是,operator new() *** 作的内部是调用了malloc()函数。

2、内存释放


同样地,delete *** 作第一步也是调用了对象的析构函数,然后再通过operator delete()函数释放内存,本质上也是调用了free函数。

3、模拟编译器直接调用构造和析构函数

#include 
#include 
#include //std::allocator

using namespace std;
namespace jj02
{
	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_call_all_ctor_directly()
	{
		cout << "ntest_call_ctor_directly().......... n";
		string* pstr = new string;
		cout << "str= " << *pstr << endl;
		//! pstr->string::string("jjhou");  
		//[Error] 'class std::basic_string' has no member named 'string'
		//! pstr->~string();	//crash -- 其語法語意都是正確的, crash 只因為上一行被 remark 起來嘛.  
		cout << "str= " << *pstr << endl;

		A* pA = new A(1);
		cout << pA->id << endl;   	//1
		pA->A::A(3);
		cout << pA->id << endl;
		//!	pA->A::A(3);                //in VC6 : ctor. this=000307A8 id=3
		//in GCC : [Error] cannot call constructor 'jj02::A::A' directly

		A::A(5);
		//!	A::A(5);	  				//in VC6 : ctor. this=0013FF60 id=5
		//         dtor. this=0013FF60  	
		//in GCC : [Error] cannot call constructor 'jj02::A::A' directly
		//         [Note] for a function-style cast, remove the redundant '::A'

		cout << pA->id << endl;   	//in VC6 : 3
		//in GCC : 1  	

		delete pA;

		//simulate new
		void* p = ::operator new(sizeof(A));
		cout << "p=" << p << endl; 	//p=000307A8
		pA = static_cast(p);
		pA->A::A(2);
		//!	pA->A::A(2);				//in VC6 : ctor. this=000307A8 id=2
		//in GCC : [Error] cannot call constructor 'jj02::A::A' directly  	

		cout << pA->id << endl;     //in VC6 : 2
		//in GCC : 0  	

		//simulate delete
		pA->~A();//先析构
		::operator delete(pA);//free()再释放内存
	}
}

int main(void)
{
	jj02::test_call_all_ctor_directly();
	return 0;
}
test_call_ctor_directly()..........
str=
str=
ctor. this=0149D1C8 id=1
1
ctor. this=0149D1C8 id=3
3
ctor. this=0118FB48 id=5
dtor. this=0118FB48 id=5
3
dtor. this=0149D1C8 id=3
p=0149FED0
ctor. this=0149FED0 id=2
2
dtor. this=0149FED0 id=2
Array new 第二讲:malloc/free 第三讲:std::allocator 第四讲:other allocators 第五讲:loki::allocator

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/zaji/5714182.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-18
下一篇 2022-12-18

发表评论

登录后才能评论

评论列表(0条)

保存