C++ Primer第五版笔记——重载new和delete

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/rest_in_peace/article/details/82965704

要想掌握重载new和delete的方法,首先要对new和delete表达式的工作机理有更多了解,当执行一条new/delete表达式时:

string* sp = new string("hello");
string* arr = new string[10];
delete sp;
delete[] arr;

对new来说实际执行了三个步骤:
第一步、new表达式调用一个operator new(或者 operator new[])的标准库函数。该函数分配一块足够大的、未命名的、原始的内存空间以便于存储特定类型的对象(或者对象数组);
第二步、编译器运行相应的构造函数以构造这些对象,并为其传入初始值;
第三步、对象被分配了空间并构造完成,返回一个指向该对象的指针。
对delete来说实际执行了两步操作:
第一步、对sp所指对象或者arr所指的对象数组中的元素执行对应的析构操作;
第二步、编译器调用operator delete(或者operator delete[])的标准库函数释放内存空间。
  应用程序可以在全局区域中定义operator new和operator delete函数(这时程序就担当起控制动态内存分配的职责,这两函数必须是正确的),也可以将他们定义为成员函数。当编译器发现一条new或delete表达式时,将在程序中寻找可供调用的operator函数,如果被分配的类型是类类型,则首先在该类及其基类中查找,没有找到则会在全局作用域中查找(也可以使用::运算符限制直接执行全局区域中的函数),仍然没有则会使用标准库定义的函数。


operator new 接口和operator delete 接口
  标准库定义了operator new函数和operator delete函数的8个重载版本。其中前4个版本可能抛出bad_alloc异常,后4个版本则不会抛出异常:

//这些版本可能抛出异常
void* operator new(size_t);							//分配一个对象
void* operator new[](size_t);						//分配一个数组
void* operator delete(void*) noexcept;		//释放一个对象
void* operator delete[](void*) noexcept;		//释放一个数组

//这些版本不会抛出异常
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;

对于operator new和operator new[]函数来说,它们的返回值必须是void*,第一个形参的类型必须是size_t且该形参不能含有默认实参。当编译器调用前者时,把存储指定类型对象所需的字节数传给size_t形参;当编译器调用后者时,传入函数的则是存储数组中所有元素所需的空间。尽管在一般情况下我们可以自定义具有任何形参的operator new,但是以下版本不能被重载:

void* operator new(size_t,void*);

对于operator delete和operator delete[]函数来说,它们的返回类型必须是void,第一个形参类型必须是void*。执行一条delete表达式将调用相应的operator函数,并用指向待释放内存的指针来初始化void*形参。
  当将这两个函数定义为类的成员时,该函数可以包含另一个size_t的形参,此时,该形参的初始值是第一个形参指向的对象的字节数。size_t形参可用于删除继承体系中的对象。如果基类有一个虚析构函数,则传递给operator delete的字节数将因待删除指针所指向的对象的动态类型的不同而有所区别。而且,实际运行的operator delete函数版本也由对象的动态类型决定。


malloc函数和free函数
  当定义了自己的全局operator new或operator delete后,必须以某种方式执行分配内存与释放内存的操作,为此可以使用malloc和free函数,c++从c语言中继承这些函数,并将其定义在cstdlib头文件中。
  malloc函数接受一个表示待分配字节数的size_t,返回指向分配空间的指针或者返回0以表示分配失败。free接受一个void*,它是malloc返回的指针的副本,free将相关内存返回给系统(调用free(0)没有意义)。


例子:

void* operator new(size_t size){
	if(void* mem = malloc(size)){
		return mem;
	}
	else{
		throw bad_malloc();	
	}
}

void operator delete(void* mem) noexcept {
	free(mem);
}

猜你喜欢

转载自blog.csdn.net/rest_in_peace/article/details/82965704