一、New和Malloc的作用
New和Malloc都是动态内存分配的函数,可以在程序运行时为变量动态分配内存。 New是C++的标准运算符,它为对象动态分配内存,并调用构造函数初始化对象。在分配内存时,不需要指定内存空间大小,因为编译器会通过类型推断自动计算内存大小。 Malloc是C语言的标准函数,它允许程序在运行时为变量分配内存。在分配内存时需要指定内存空间大小,也就是分配的字节数。
// New的示例代码
#include<iostream>
using namespace std;
int main() {
int *p = new int;
*p = 10;
cout << *p << endl;
delete p;
return 0;
}
// Malloc的示例代码
#include <stdio.h>
#include <stdlib.h>
int main() {
int *p = (int*)malloc(sizeof(int));
*p = 10;
printf("%d\n", *p);
free(p);
return 0;
}
二、New和Malloc的实现方式
New和Malloc的实现方式不同。 New是调用operator new函数来实现动态内存分配。当执行new操作时,编译器首先调用operator new函数来分配内存,然后才调用构造函数来初始化对象。用户可以重载operator new来改变内存分配策略。 Malloc是调用操作系统提供的动态内存分配函数来实现的。操作系统为Malloc分配的内存会放在内存堆中,由程序员负责管理。Malloc分配的内存空间可以通过free释放掉。
// operator new的示例代码
#include<iostream>
using namespace std;
void* operator new(size_t n)
{
cout << "Allocating " << n << " bytes." << endl;
void* p = malloc(n);
return p;
}
void operator delete(void* p)
{
cout << "Deallocating memory." << endl;
free(p);
}
class Student {
public:
Student() {
cout << "Constructing Student object." << endl;
}
~Student() {
cout << "Destructing Student object." << endl;
}
};
int main() {
Student* pStu = new Student;
delete pStu;
return 0;
}
三、New和Malloc的错误处理
New和Malloc的错误处理方式也不同。 New在分配内存失败时,会抛出std::bad_alloc异常。程序员可以通过捕获这个异常来处理分配内存失败的情况,也可以选择不处理,让程序崩溃。 而Malloc在分配内存失败时,返回NULL指针。程序员需要在分配内存操作后检查返回值是否为NULL,如果是,说明内存分配失败。
// std::bad_alloc的示例代码
#include<iostream>
#include <new>
using namespace std;
int main() {
try {
int* p = new int[1000000000000000];
}
catch (bad_alloc& e) {
cout << "Allocation failed: " << e.what() << endl;
}
return 0;
}
// Malloc返回NULL指针的示例代码
#include <stdio.h>
#include <stdlib.h>
int main() {
int *p = (int*)malloc(sizeof(int)*1000000000000000);
if(p == NULL) {
printf("Allocation failed\n");
exit(1);
}
free(p);
return 0;
}
四、New和Malloc的适用场景
New和Malloc适用于不同的场景。 New适用于C++中对象的动态分配,可以自动调用构造函数初始化对象。 而Malloc适用于C语言中变量的动态分配,不会调用构造函数,程序员需要手动初始化变量。Malloc还适用于内存池的实现,因为它可以在堆中分配一段连续的内存空间。
// 适用New的示例代码
#include<iostream>
using namespace std;
class Person {
public:
Person(int age) : m_age(age) {
}
void printAge() {
cout << "Age: " << m_age << endl;
}
private:
int m_age;
};
int main() {
Person* p = new Person(20);
p->printAge();
delete p;
return 0;
}
// 适用Malloc的示例代码
#include <stdio.h>
#include <stdlib.h>
struct Student {
int id;
int age;
};
int main() {
// 手动初始化
struct Student* pStu = (struct Student*)malloc(sizeof(struct Student));
pStu->id = 1;
pStu->age = 20;
printf("id: %d, age: %d\n", pStu->id, pStu->age);
free(pStu);
return 0;
}
五、New和Malloc的内存对齐
New和Malloc在分配内存时都要考虑内存对齐的问题。 C++中的new运算符会保证分配的内存空间满足所分配类型的对齐要求。例如,如果分配一个int类型的内存空间,那么它的起始地址必定是4的倍数。 而C语言的malloc函数则需要手动指定分配的内存空间大小,也需要手动保证内存对齐。
// New的内存对齐示例代码
#include<iostream>
using namespace std;
class Student {
public:
Student(int age) : m_age(age) {
}
void printAge() {
cout << "Age: " << m_age << endl;
}
private:
int m_age;
};
int main() {
Student* p = new Student(20);
cout << "sizeof(Student): " << sizeof(Student) << endl;
cout << "p address: " << p << endl;
delete p;
return 0;
}
// Malloc的内存对齐示例代码
#include <stdio.h>
#include <stdlib.h>
int main() {
// 分配8字节内存,但只使用了4字节
int* p = (int*)malloc(sizeof(int));
// 输出指针地址,和所占字节数
printf("p address: %p, size: %u\n", p, sizeof(*p));
free(p);
return 0;
}