概述
new
/delete
是 C++ 的关键字,需要编译器支持。malloc
/free
是库函数,需要头文件支持。- 使用
new
申请内存分配时无需指定内存块大小,编译器会自动计算。而malloc
需要明确指定所需内存的大小。 new
会返回对象类型的指针,类型安全。而malloc
返回void*
,需要进行强制类型转换。new
分配内存失败时会抛出std::bad_alloc
异常。malloc
分配内存失败时返回NULL
。new
会调用构造函数,delete
会调用析构函数。malloc
/free
只负责内存的分配和释放,不会调用构造或析构函数。
详细解释
new
/delete
是 C++ 的关键字,而malloc
/free
是标准库函数。
示例:
#include <iostream>
#include <cstdlib> // for malloc and free
int main() {
// 使用new关键字
int* p1 = new int(5); // 分配并初始化int
delete p1; // 删除并释放内存
// 使用malloc/free函数
int* p2 = (int*)malloc(sizeof(int)); // 分配内存,返回 void*
*p2 = 5; // 初始化int
free(p2); // 释放内存
return 0;
}
new
不需要指定内存块大小,而malloc
需要明确指出大小。
示例:
#include <iostream>
#include <cstdlib>
int main() {
// 使用new操作符分配内存,编译器自动计算所需内存大小
int* p1 = new int[10]; // 分配10个int的数组
delete[] p1; // 使用delete[]释放数组内存
// 使用malloc函数分配内存,需明确指定大小
int* p2 = (int*)malloc(10 * sizeof(int)); // 分配10个int的数组
free(p2); // 使用free释放内存
return 0;
}
new
返回对象类型的指针,而malloc
返回void*
需要强制类型转换。
示例:
// 无需转换类型的情况
double* p1 = new double(3.14); // 分配并初始化double
delete p1; // 删除内存
// 需要强制转换类型的情况
double* p2 = (double*)malloc(sizeof(double)); // 分配内存
*p2 = 3.14; // 初始化
free(p2); // 释放内存
new
分配内存失败时抛异常,malloc
分配内存失败返回NULL
。
示例:
#include <iostream>
#include <new>
#include <cstdlib>
int main() {
try {
int* p1 = new int[1000000000000]; // 可能抛出异常
delete[] p1;
} catch (std::bad_alloc& e) {
std::cerr << "Memory allocation failed: " << e.what() << std::endl;
}
int* p2 = (int*)malloc(1000000000000 * sizeof(int)); // 可能返回NULL
if (p2 == NULL) {
std::cerr << "Memory allocation failed" << std::endl;
} else {
free(p2);
}
return 0;
}
new
调用构造函数,delete
调用析构函数。
示例:
#include <iostream>
#include <cstdlib>
class MyClass {
public:
MyClass() { std::cout << "Constructor called." << std::endl; }
~MyClass() { std::cout << "Destructor called." << std::endl; }
};
int main() {
// 使用new,自动调用构造函数
MyClass* obj1 = new MyClass();
delete obj1; // 自动调用析构函数
// 使用malloc,必须手动调用构造和析构函数
void* mem = malloc(sizeof(MyClass));
MyClass* obj2 = new (mem) MyClass(); // 使用placement new 调用构造函数
obj2->~MyClass(); // 手动调用析构函数
free(mem); // 释放内存
return 0;
}
delete p;
与 delete[] p;
以及 allocator
- 动态数组管理中,
new[]
要求数组大小为整数但不一定是常量,普通数组必须是常量。 new
动态数组返回元素类型的指针,而不是数组类型。delete[]
会按逆序销毁数组中的元素。allocator
分开内存分配和对象构造,提供更灵活的对象管理。
示例:
#include <iostream>
#include <memory> // for std::allocator
class MyClass {
public:
MyClass() { std::cout << "Constructor called." << std::endl; }
~MyClass() { std::cout << "Destructor called." << std::endl; }
};
int main() {
// 使用new和delete[]管理动态数组
MyClass* arr = new MyClass[3]; // 分配数组并调用构造函数
delete[] arr; // 逆序调用析构函数并释放内存
// 使用allocator分配内存和构造对象
std::allocator<MyClass> alloc;
MyClass* mem = alloc.allocate(3); // 分配未初始化内存
alloc.construct(mem, MyClass()); // 默认初始化第一个对象
alloc.construct(mem + 1, MyClass()); // 默认初始化第二个对象
alloc.construct(mem + 2, MyClass()); // 默认初始化第三个对象
// 销毁对象和释放内存
alloc.destroy(mem);
alloc.destroy(mem + 1);
alloc.destroy(mem + 2);
alloc.deallocate(mem, 3);
return 0;
}
结论
以上示例和解释展示了 new
/delete
与 malloc
/free
在 C++ 中的不同以及正确使用方法。通过学习和理解这些内容,可以更好地管理动态内存,提高程序的安全性和稳定性。