📅  最后修改于: 2023-12-03 15:08:30.768000             🧑  作者: Mango
在C++中,我们常常需要在堆上动态分配对象,但是有时候我们希望我们的类只能在堆上被动态分配,而不能在栈上被静态分配。这可以通过重载 new
和 delete
运算符来实现。
在C++中,我们可以通过重载 new
和 delete
运算符来实现堆上动态分配内存的方式。为了实现只能在堆上动态分配的类,我们需要重载全局的 new
和 delete
运算符,并在类内定义私有的 operator new
和 operator delete
运算符。
class HeapOnly {
public:
void foo() {
std::cout << "Hello, World!\n";
}
private:
void* operator new(std::size_t size);
void operator delete(void* ptr);
};
void* HeapOnly::operator new(std::size_t size) {
void* ptr = malloc(size);
if (ptr == nullptr) {
throw std::bad_alloc();
}
return ptr;
}
void HeapOnly::operator delete(void* ptr) {
free(ptr);
}
int main() {
// 尝试在栈上实例化 HeapOnly 类
HeapOnly heapOnly; // 编译错误,HeapOnly 类不能在栈上实例化
// 在堆上动态分配 HeapOnly 类的实例
HeapOnly* heapOnlyPtr = new HeapOnly;
heapOnlyPtr->foo(); // 输出 `Hello, World!`
delete heapOnlyPtr;
return 0;
}
在上面的代码中,我们重载了 HeapOnly
的 new
和 delete
运算符,使得我们的类只能在堆上被动态分配。
为了保证我们的类只能动态分配,我们还需要禁止拷贝和赋值。我们可以通过私有化拷贝构造函数和赋值运算符来实现:
class HeapOnly {
public:
void foo() {
std::cout << "Hello, World!\n";
}
private:
// 禁止拷贝和赋值
HeapOnly(const HeapOnly&);
HeapOnly& operator=(const HeapOnly&);
void* operator new(std::size_t size);
void operator delete(void* ptr);
};
void* HeapOnly::operator new(std::size_t size) {
void* ptr = malloc(size);
if (ptr == nullptr) {
throw std::bad_alloc();
}
return ptr;
}
void HeapOnly::operator delete(void* ptr) {
free(ptr);
}
int main() {
// 尝试在栈上实例化 HeapOnly 类
HeapOnly heapOnly; // 编译错误,HeapOnly 类不能在栈上实例化
// 在堆上动态分配 HeapOnly 类的实例
HeapOnly* heapOnlyPtr1 = new HeapOnly;
HeapOnly* heapOnlyPtr2 = new HeapOnly(*heapOnlyPtr1); // 编译错误,禁止拷贝构造函数
HeapOnly* heapOnlyPtr3 = new HeapOnly;
*heapOnlyPtr3 = *heapOnlyPtr1; // 编译错误,禁止赋值运算符
heapOnlyPtr1->foo(); // 输出 `Hello, World!`
delete heapOnlyPtr1;
delete heapOnlyPtr2;
delete heapOnlyPtr3;
return 0;
}
通过重载 new
和 delete
运算符,并私有化拷贝构造函数和赋值运算符,我们可以实现只能在堆上动态分配的C++类。