如何构造只能在堆/栈上创建对象的类

核心思想:****阻止栈资源的释放 当编译器在栈上分配资源时,必须确保其能够在离开作用域时通过调用析构函数被释放。如果人为指定析构函数不可见,那么编译器就会报错,从而阻止了栈上的资源分配。也就是说,需要**破坏编译器在在栈上自动管理生命周期的能力**: private : HeapOnly() = default; 此时类对象位于堆上,需要通过指针进行管理,因此在类中定义一个“静态工厂函数”: static std::unique_ptr create(){ return std::unique_ptr(new HeapOnly()); } 二:只能在栈上创建对象的类 核心思想:禁止一切形式的 new 操作 当我们在外部使用“new T()”创建类对象时,编译器会在类或全局作用域下寻找 new 的重载,如果将 new 标记为 delete,就能从源头切断堆上的分配: // 禁止单个对象的堆分配 void* operator new(std::size_t)= delete; void operator delete(void*)= delete; // 禁止数组形式的堆分配 void* operator new[](std::size_t) = delete; void operator delete[](void*) = delete;

May 10, 2026 · 1 min · 榎aaaa

Fundamentals of Cpp:现代 C++ 核心笔记

这里是整理的一些c++基础知识…. 就这样吧…. 语法 1.C++的三大特性 封装,继承,多态(同时也是面向对象编程的三大特性) 1).简要解释一下上面三者 ·封装:隐藏内部具体的实现细节,对外部只暴露必要的接口来访问对象 ·继承:允许一个类从另一个类继承属性和方法,从而实现代码复用和层次化抽象 ·多态:同一个函数名拥有多种状态,或是同一个接口具有不同的行为 LINK: 如何理解面向对象编程三大特性——封装、继承、多态 2).多态的类别 ·运行时多态(动态联编):通过继承和虚函数实现 ·编译时多态(静态联编):通过重载和模板实现 2.虚函数 简单来说,虚函数就是允许在基类(父类)中定义一个函数,并允许派生类(子类)对其进行重写 (Override) 1).虚函数的实现机制 ·通过虚函数表实现,虚函数表是一个由编译器生成的静态数组,位于类的全局静态内存区中,包含了一个类所有的虚函数的地址(即该类所有虚函数的入口) ·在类对象(不是类!)内存空间的头部,有一个虚函数表指针,它指向该类虚函数表的首地址 ·当子类对象对父类虚函数进行重写的时候,虚函数表中相应的虚函数的地址会被更改为重写后的虚函数地址 2).虚函数调用是在编译时确定还是运行时确定的?如何确定调用哪个函数? ·一般来说是在运行时确定,可以通过虚函数表中的地址来确定调用什么函数 3).能否在基类的构造函数和析构函数中调用虚函数? ·在语法上来说没有问题,但是在实际调用时,无法实现多态的效果,因为构造函数会先初始化基类的成员,而此时子类的成员还是一片空白,如果这时使用子类中还未被初始化的成员,会出现错误;同理,析构函数是先从子类开始析构,如果在基类的析构函数中调用虚函数的话,因为此时子类已经被析构,是无法调用其特有成分的 4).当一个类需要被继承时,它的析构函数必须是虚函数 如果基类的析构函数不为虚函数,那么当对派生类对象进行删除(delete)操作时,就只会调用基类的析构函数,这会导致内存泄漏; 而当基类包含虚析构函数时,在同样的情况下,编译器会先查询虚函数表,并调用对应的析构函数 3.C++的内存管理 1).C++有哪些内存区域 ·栈:由编译器自动分配与释放,多用于存储局部变量;速度极快,但空间有限(通常只有几MB) ·堆:需要手动控制生存周期, 从 new 或 malloc 开始,直到 delete 或 free;空间极大,分配位置不连续 ·全局/静态存储区: 存储全局变量和静态变量,在程序启动时分配,程序退出时才释放 ; .data 段:存储已初始化的全局/静态变量。 .bss 段:存储未初始化的全局/静态变量(自动初始化****为 0)。 ·常量存储区: 存储只读数据 ·自由存储区:通过new和delete分配和释放空间的内存,具体实现可能是堆或者内存池 ·代码区:存储经过编译之后的机器指令(二进制代码) Link: C++内存管理 - 还没放弃的老张 - 博客园 2).栈 与 堆 的区别 1.堆的内存空间大,栈的内存空间小 ...

April 19, 2026 · 3 min · 榎aaaa