Step to UEFI (288)Cpp UEFI 004 C++ 的 New 和 Delete

C++还有两个重要的函数:new 和 delete。根据《UEFI 原理与编程》 10.2.6 讲述,我们需要自行实现函数。

上述书籍对应的代码提供了 new 和 delete 的实现,可以看到基本的思路就是使用 gSt-> BootServices ->AllocatePool 分配和gSt-> BootServices->FreePool回收内存:

#include <UEFI/UEFI.h>
#include <type_traits>

EFI_SYSTEM_TABLE* gSt;

typedef UINTN size_t;

void *  operator new( size_t Size )
{
    void       *RetVal;
    EFI_STATUS  Status;

    if( Size == 0) {
        return NULL;
    }

    Status = gSt-> BootServices ->AllocatePool( EfiLoaderData, (UINTN)Size, &RetVal);
    if( Status != EFI_SUCCESS) {
        RetVal  = NULL;
    }
    return RetVal;
}


void *  operator new[]( size_t cb )
{
    void *res = operator new(cb);
    return res;
}

void operator delete( void * p )
{ 
  if(p != NULL) 
    (void) gSt-> BootServices->FreePool (p);
}

void operator delete[]( void * p )
{
    operator delete(p);
}

void printInt(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL* conOut, int value) {
	CHAR16 out[32];
	CHAR16* ptr = out;
	static_assert(std::is_unsigned_v<char16_t>);
	if (value == 0)
	{
		conOut->OutputString(conOut, u"0");
		return;
	}

	ptr += 31;
	*--ptr = 0;
	int tmp = value;// >= 0 ? value : -value; 

	while (tmp)
	{
		*--ptr = '0' + tmp % 10;
		tmp /= 10;
	}

	if (value < 0) *--ptr = '-';
	conOut->OutputString(conOut, ptr);
}

EFI_STATUS
efi_main(EFI_HANDLE /*image*/, EFI_SYSTEM_TABLE* systemTable)
{
	gSt=systemTable;
	int *p=new int;
	
	*p=123;
	
	printInt(gSt->ConOut,*p);
	gSt->ConOut->OutputString(gSt->ConOut, u"\r\n");

	delete p;
	
	return EFI_SUCCESS;
}

运行之后可以在屏幕上看到 123 的字样。

接下来实验使用 new 和 delete 创建对象的情况,基本的代码如下:

class Time {
 
public:
	Time() {//构造函数
		gSt->ConOut->OutputString(gSt->ConOut, u"Init\n\r");
	}
	~Time(){//析构函数
		gSt->ConOut->OutputString(gSt->ConOut, u"Destroy\n\r");
    }
 
private:
	int _hour;
	int _min;
	int _sec;
};

EFI_STATUS
efi_main(EFI_HANDLE /*image*/, EFI_SYSTEM_TABLE* systemTable)
{
	gSt=systemTable;
	Time *myTime=new Time;
	delete myTime;
	return EFI_SUCCESS;
}

运行结果如下:

可以看到,当我们 new 创建对象的时候,自动运行了 Time 的构造函数。构造函数的作用是:当该类对象被创建的时候,编译系统对象分配内存空间,并自动调用该构造函数,由构造函数完成成员的初始化工作,故:构造函数的作用:初始化对象的数据成员。同样的还有一个“析构函数”,用于做一些清理的洞动作。

有兴趣的朋友可以进一步阅读如下文件:

  1. https://blog.csdn.net/qq_21438461/article/details/129651522 C/C++ 内存分配 new 操作符:剖析new操作符的实现机制和使用技巧
  2. https://blog.csdn.net/sinat_31608641/article/details/102892951 C++关键字new的原理

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注