编译器控件如何帮助分配和解分配C++内存?

How does the compiler control help in allocating & deallocating memory in C++?

本文关键字:分配 和解 C++ 内存 帮助 控件 何帮助 编译器      更新时间:2023-10-16

我在一本C++书中读到malloc()&free()是liabrary函数,因此不在编译器的控制范围内。

但是,如果您有一个操作员来执行动态存储分配&初始化(new)和另一个操作员执行清理&释放存储(delete),编译器仍然可以保证构造函数&将为所有对象调用析构函数。

所以,我想知道编译器是如何实现的?将通知任何示例或演示。

提前谢谢。

malloc函数返回一块连续内存,仅此而已。如何键入类型转换并使用它(用于对象)是您的问题。

new运算符返回在内存中分配的对象。尽管两者都返回一个指针,但最终您得到的是构造的对象,而不是C++中的原始内存。这里的重点从低级内存处理转移到对象处理,随之而来的是类型安全。这就是new不返回void*的原因。

此外,如果你注意到,在前一种情况下,C是一个进行分配的函数,即语言本身没有分配对象或内存的概念。而在C++中,new是一个运算符,因此该语言本质上理解动态创建对象的含义。编译器实现了语言规定的内容,因此在发现错误时可以标记错误。

例如:

int *ptr = malloc(sizeof(char) * 4);

这里,程序员假设一个整数的大小4,虽然这在他的平台中可能是真的,但并非所有平台都是真的。从概念上讲,charint是不同的类型,但C编译器忽略了类型不匹配。它所做的只是调用malloc函数,并将返回的地址分配给ptr。它的域到此为止,由程序员来使用(或滥用?)分配的内存。这不是编译器的错误或弱点,因为语言标准没有赋予编译器更多的权力来强制执行更多。

在C++中

int *ptr = new char[4];

将被标记为错误;正确的方法是CCD_ 14,其中类型匹配。C++更严格,在错误常见的地方允许较小的自由度,从而产生更干净的代码。类型安全可以说是C++语言最大的安全特性。出于同样的原因,类型转换有一个丑陋的语法:它们显示了设计的弱点。使用更严格的语言,编译器能够对开发人员实施更多的限制(因为人类更容易出错,所以在大多数情况下效果很好)。

编译器并没有真正直接"帮助"分配和释放内存;您的代码必须明确地执行此操作。当线程离开作用域(析构函数)时,C++语言提供了代码的确定性执行。这反过来通常用于释放堆分配的内存。

new和delete是c++中的关键词。

C++编译器会为您生成隐藏代码来处理内存分配/释放的问题。

例如,

struct Test() { }
Test *a = new Test();

编译器可能会这样做,(以下是伪代码)

Test *a = (Test *)malloc(sizeof(Test));
if (a == nullptr) { throw std::bad_alloc; }
try
{
a.Test(); //call constructor
}
catch (...)
{
//constructor exception, free the memory first, then re-throw
free(a);
throw;
}

如果是阵列,事情会更复杂,

struct Test() { }
Test *a = new Test[10];

编译器可能会这样做,

Test *a = (Test *)malloc(sizeof(Test) * 10);
if (a == nullptr) { throw std::bad_alloc; }
int i;
try
{
for (i = 0; i < 10, i++)
a[i].Test(); //call constructor
}
catch (...)
{
//call destructor for all constructed objects
for (int j = 0; j < i; j++)
a[j].~Test();
free(a);
throw;
}

类似的逻辑适用于删除。