1. new
和 new[]
的工作原理
简单类型:
- 使用
operator new
分配内存。 - 如果是
new[]
(数组),计算总大小后一起分配。
复杂类型(类对象等):
- 先调用
operator new
分配内存。 - 然后在分配的内存上调用构造函数。
- 对于
new[]
(对象数组),先调用operator new[]
分配内存,并在内存区域前部保存数组大小,然后调用构造函数。
示例及注释:
#include <iostream>
#include <new> // For std::bad_alloc
class MyClass {
public:
MyClass() { std::cout << "Constructor called" << std::endl; }
~MyClass() { std::cout << "Destructor called" << std::endl; }
void* operator new(size_t size) {
std::cout << "operator new called" << std::endl;
return ::operator new(size);
}
void operator delete(void* ptr) {
std::cout << "operator delete called" << std::endl;
::operator delete(ptr);
}
void* operator new[](size_t size) {
std::cout << "operator new[] called" << std::endl;
return ::operator new(size);
}
void operator delete[](void* ptr) {
std::cout << "operator delete[] called" << std::endl;
::operator delete(ptr);
}
};
int main() {
// 单个对象
MyClass* obj = new MyClass(); // 调用 operator new 和构造函数
delete obj; // 调用析构函数和 operator delete
// 对象数组
MyClass* array = new MyClass[3]; // 调用 operator new[] 和每个对象的构造函数
delete[] array; // 调用每个对象的析构函数和 operator delete[]
return 0;
}
2. delete
和 delete[]
的工作原理
简单类型:
- 直接调用
free
函数。
复杂类型(类对象等):
- 调用析构函数释放资源。
- 直接调用
operator delete
释放内存。 - 对于
delete[]
,从内存区域读取数组大小,再依次调用析构函数后,再调用operator delete[]
释放整体内存。
示例及注释:
#include <iostream>
#include <cstdlib> // For malloc and free
class Complex {
private:
int* data;
public:
Complex() {
data = new int[10]; // Allocate resource
std::cout << "Complex Constructor called" << std::endl;
}
~Complex() {
delete[] data; // Release resource
std::cout << "Complex Destructor called" << std::endl;
}
};
int main() {
// 简单类型
int* p = static_cast<int*>(std::malloc(sizeof(int)));
*p = 10;
std::free(p); // 释放内存,不涉及构造和析构函数
// 复杂类型
Complex* obj = new Complex(); // 调用 operator new 和构造函数
delete obj; // 调用析构函数和 operator delete
// 复杂类型数组
Complex* array = new Complex[3]; // 调用 operator new[] 和每个对象的构造函数
delete[] array; // 调用每个对象的析构函数和 operator delete[]
return 0;
}
3. 内存布局和 delete[]
释放内存的工作机制
new
和new[]
在分配内存时,如果是数组,会在分配的内存块前部预留额外的空间存储数组大小。
示例及注释:
#include <iostream>
#include <cstdlib> // for malloc and free
void* operator new[](size_t size) {
void* ptr = std::malloc(size + sizeof(size_t));
if (!ptr) throw std::bad_alloc();
*static_cast<size_t*>(ptr) = size; // Store size at the start
return static_cast<void*>(static_cast<char*>(ptr) + sizeof(size_t));
}
void operator delete[](void* ptr) noexcept {
if (!ptr) return;
void* realPtr = static_cast<void*>(static_cast<char*>(ptr) - sizeof(size_t));
size_t size = *static_cast<size_t*>(realPtr);
std::free(realPtr);
}
class MyClass {
public:
int x;
~MyClass() { std::cout << "MyClass Destructor called" << std::endl; }
};
int main() {
MyClass* arr = new MyClass[3]; // operator new[] called
delete[] arr; // Calls destructors then operator delete[]
return 0;
}
结论
上面的代码示例和注释详细说明了 new
与 delete
的工作原理,特别是对于 C++ 中复杂类型和数组的内存管理方式。通过这些知识,可以深入理解 C++ 动态内存管理机制,提高编程的可靠性和效率。