全局 new
重载
void* operator new(size_t size) {
// 输出内存分配大小
char msg[] = "Global operator new called. Size: ";
write(1, msg, sizeof(msg) - 1);
void* ptr = malloc(size); // 使用 malloc 分配内存
if (!ptr) throw "Memory allocation failed"; // 分配失败时抛出异常
return ptr;
}
类内 new
重载
class MyClass {
public:
// 类专用 new 运算符
void* operator new(size_t size) {
// 输出类内内存分配信息
char msg[] = "Class-specific operator new called.";
write(1, msg, sizeof(msg) - 1);
void* ptr = malloc(size); // 分配内存
if (!ptr) throw "Memory allocation failed";
return ptr;
}
// 类专用 delete 运算符
void operator delete(void* ptr) {
char msg[] = "Class-specific operator delete called.";
write(1, msg, sizeof(msg) - 1);
free(ptr); // 释放内存
}
};
说明
- 使用了
write
输出,避免依赖任何 C++ 标准库。 - 使用
malloc
和free
进行底层内存操作。 - 抛出了简单字符串异常,替代标准异常类型。
使用示例
int main() {
MyClass* obj = new MyClass(); // 调用类内 `new`
delete obj; // 调用类内 `delete`
void* globalMem = operator new(32); // 调用全局 `new`
operator delete(globalMem); // 调用全局 `delete`
return 0;
}
输出结果
- 调用类内
new
和delete
时,会打印类相关的分配和释放信息。 - 调用全局
new
和delete
时,会打印全局的分配信息
new
重载解释
在 C++ 中,new
操作符用于动态分配内存。当你在程序中使用 new
,默认情况下,它调用标准库中预定义的内存分配机制。这种行为可以通过重载 operator new
来定制,以便实现自定义的内存管理。
为什么需要重载 new
?
- 优化内存分配:通过重载,可以定制内存分配策略(如内存池)。
- 调试和跟踪:插入日志,用于检测内存分配是否成功,追踪内存泄漏。
- 特殊需求:为特定类分配特殊的内存块,或对分配的内存进行预处理。
2. 类特定的 new
和 delete
重载
你可以为特定的类重载 new
和 delete
操作符,这种重载只会影响该类的对象,不会影响其他类或全局的内存分配行为。
示例代码
#include <iostream>
#include <cstdlib>
class MyClass {
public:
// 重载类的 new 操作符
void* operator new(size_t size) {
cout << "MyClass::new called. Size: " << size << endl;
void* ptr = malloc(size); // 使用 malloc 分配内存
if (!ptr) {
throw bad_alloc(); // 分配失败时抛出异常
}
return ptr;
}
// 重载类的 delete 操作符
void operator delete(void* ptr) noexcept {
cout << "MyClass::delete called." << endl;
free(ptr); // 释放内存
}
};
int main() {
MyClass* obj = new MyClass(); // 使用自定义的 new
delete obj; // 使用自定义的 delete
return 0;
}
输出结果
MyClass::new called. Size: 1
MyClass::delete called.
解释
-
operator new
重载:- 动态分配内存时调用。
- 参数
size
表示分配内存的字节数。 - 必须返回一个有效的内存地址。
-
operator delete
重载:- 释放内存时调用。
- 接受一个指向释放内存的指针。
3. 参数化的 new
重载
可以为 operator new
添加额外的参数,实现更灵活的分配逻辑。
示例代码
#include <iostream>
#include <cstdlib>
class MyClass {
public:
// 带参数的 new 重载
void* operator new(size_t size, const char* msg) {
cout << "Custom new called with message: " << msg << endl;
void* ptr = malloc(size); // 分配内存
if (!ptr) {
throw bad_alloc();
}
return ptr;
}
void operator delete(void* ptr) noexcept {
cout << "Custom delete called." << endl;
free(ptr); // 释放内存
}
};
int main() {
MyClass* obj = new ("Allocating MyClass") MyClass(); // 传递额外参数
delete obj;
return 0;
}
输出结果
Custom new called with message: Allocating MyClass
Custom delete called.
解释
- 参数化
new
:- 自定义的
new
可以接收额外的参数,如字符串、整型等。 - 在调用时使用
new (参数) 类型
的语法。
- 自定义的
4. 区分 new
和 new[]
operator new
是为单个对象分配内存。operator new[]
是为对象数组分配内存。- 它们分别可以通过重载
operator delete
和operator delete[]
配对使用。
示例代码
#include <iostream>
#include <cstdlib>
class MyClass {
public:
void* operator new(size_t size) {
cout << "Single object allocation." << endl;
return malloc(size);
}
void* operator new[](size_t size) {
cout << "Array allocation." << endl;
return malloc(size);
}
void operator delete(void* ptr) noexcept {
cout << "Single object deallocation." << endl;
free(ptr);
}
void operator delete[](void* ptr) noexcept {
cout << "Array deallocation." << endl;
free(ptr);
}
};
int main() {
MyClass* obj = new MyClass(); // 调用单对象的 new
MyClass* arr = new MyClass[3]; // 调用数组的 new[]
delete obj;
delete[] arr;
return 0;
}
输出结果
Single object allocation.
Array allocation.
Single object deallocation.
Array deallocation.
注意事项
-
必须成对使用
new
和delete
:- 如果使用
operator new
分配内存,必须使用对应的operator delete
释放内存。 - 同理,
operator new[]
必须配对operator delete[]
。
- 如果使用
-
分配失败处理:
- 默认情况下,
new
失败时会抛出std::bad_alloc
异常。 - 使用
std::nothrow
可以避免抛异常:int* p = new (nothrow) int; if (!p) { cout << "Memory allocation failed." << endl; }
- 默认情况下,
-
内存对齐和优化:
- 自定义
new
重载时,可以考虑内存对齐和缓存优化。
- 自定义
-
避免过度复杂化:
- 不必要的
new
重载可能导致代码难以维护,建议在确有需求时才使用。
- 不必要的
总结
new
重载是 C++ 中强大的内存管理工具,通过重载可以:
- 优化内存分配。
- 增强调试能力。
- 满足特定的分配需求(如内存池)。
使用时要注意匹配调用、内存安全和代码可维护性。