小学生学C++编程语法知识(C++中如何实现“只能静态分配”和“只能动态分配”的类?)
什么叫静态分配什么叫动态分配假设有一个学生对象Student stu;这个对象放在哪里通常栈区 (Stack)这种叫静态分配stack allocation如果Student *p new Student();对象在哪里堆区 (Heap)这种叫动态分配heap allocation生活比喻静态分配像爸爸妈妈给你买了一间固定房子。出生Student s;离开作用域}自动销毁。动态分配像去租房子。申请new Student();不用了delete;自己归还。一、如何实现“只能动态分配”的类也就是说我们希望允许Student *p new Student();但是禁止Student s;怎么办方法把析构函数设为 private例如class Student { private: ~Student() { } public: Student() { } }; int main() { Student s; //错误 Student *pnew Student(); //也错误 }为什么因为对象销毁的时候Student s;系统自动调用s.~Student();但是析构函数private外面不能访问。所以编译错误。但是注意这样Student *pnew Student();也不行。为什么因为以后delete p;需要调用~Student()但是析构函数private。所以无法delete。正确方法让用户不能delete提供自己的释放函数。例如class Student { private: Student() { } ~Student() { } public: static Student* create() { return new Student(); } void destroy() { delete this; } };使用Student *pStudent::create(); p-destroy();但是这里有一个问题构造函数也private了。为什么因为如果不限制Student s;还是可以创建。所以只能动态分配类关键构造函数 private 析构函数 private 提供创建函数完整class Student { private: Student() { cout创建endl; } ~Student() { cout销毁endl; } public: static Student* create() { return new Student(); } void destroy() { delete this; } };使用int main() { Student *pStudent::create(); p-destroy(); }输出创建 销毁二、为什么要设计只能动态分配有什么用例如1. 单例模式很多系统对象只能有一个。比如游戏中的服务器数据库连接日志系统希望Server s;不允许。只能Server::getInstance();统一管理。2. 控制生命周期比如一个网络连接希望程序运行期间一直存在。不希望离开函数自动消失。三、如何实现“只能静态分配”的类现在反过来。希望允许Student s;禁止Student *pnew Student();也就是只能栈上创建。方法让 new 失败。C中new实际上调用operator new()所以我们禁止它。代码class Student { public: Student() { } private: void* operator new(size_t) { return nullptr; } };现在Student s;可以。因为直接创建。但是Student *pnew Student();会调用operator new而它是private。所以错误。四、为什么operator new可以控制new很多小朋友认为new Student()只是创建对象。其实它分两步第一步申请空间operator new()第二步调用构造函数Student()例如new Student();类似申请内存 | ↓ 调用构造函数 | ↓ 对象出生所以控制operator new就可以控制动态创建。五、实际工程中的应用1. 只能动态分配常见单例模式例如class Database { private: Database(){} public: static Database get() { static Database db; return db; } };2. 只能静态分配比较少见。例如一些轻量对象希望不允许new防止大量创建生命周期简单六、容易混淆的问题问构造函数private是不是只能动态分配答不一定。例如class A { private: A(){} };结果什么都不能创建。因为外部A a;不行。new A();也不行。必须提供接口。例如static A* create();七、小学生记忆口诀只能动态分配想象房子只能租不能买。做法构造函数 private 析构函数 private 提供 create()只能静态分配想象只能住学校宿舍不能出去租房。做法public 构造函数 private operator new()八、总结表目标禁止实现只能动态分配栈对象构造函数private普通delete析构函数private提供create/destroy只能静态分配new创建重载operator new为private最后给学生一个总结C中控制对象在哪里创建本质是在控制两个入口创建入口构造函数内存申请入口operator new控制这两个入口就可以控制对象只能在栈上创建或者只能在堆上创建。这个知识点也是理解C对象生命周期、RAII、单例模式、智能指针设计的基础。