C++中调用Game类Tick时触发所有Object实例同名函数是否可行?
性能误区先澄清
你认为std::vector遍历速度慢是没有实际依据的:std::vector底层是连续内存,遍历的缓存命中率极高,是C++标准容器中遍历效率最高的实现之一。对于普通小游戏来说,哪怕你有数千个对象每帧遍历,开销都可以忽略不计,完全达不到性能瓶颈。
不用外部容器的实现方案
如果不想手动维护外部的对象容器,可以通过给Object类增加静态链表的方式实现自动注册/注销,所有实例在构造时自动加入全局链表,析构时自动移除,Game的Tick只需要遍历这个静态链表即可:
#include <iostream> #include <string> #include <utility> class Object { public: static Object* head; // 静态链表头指针 Object* next; // 单链表后继指针 std::string Name; Object(std::string name) : Name(std::move(name)) { // 构造时插入链表头部 next = head; head = this; } virtual ~Object() { // 析构时从链表中移除当前实例 if (head == this) { head = next; return; } Object* prev = head; while (prev && prev->next != this) { prev = prev->next; } if (prev) { prev->next = next; } } virtual void Tick() { std::cout << Name << std::endl; } }; // 静态成员初始化 Object* Object::head = nullptr; class Game { public: void Tick() { // 遍历静态链表调用所有Object及其派生类实例的Tick for (Object* cur = Object::head; cur; cur = cur->next) { cur->Tick(); } } }; int main() { Game game; Object obj1("obj1"), obj2("obj2"); while (true) { game.Tick(); // 测试用终止条件,实际开发可替换为游戏退出判断 break; } return 0; }
该方案的优缺点:
- 优点:不需要手动维护外部容器,新增
Object实例自动加入调度 - 缺点:静态链表全局唯一,不支持多
Game实例场景,且链表遍历缓存命中率远低于std::vector,实际性能反而更差
更推荐的实现方案
还是建议用std::vector来维护对象列表,你可以把容器封装在Game类内部,对外提供注册接口,逻辑更清晰、生命周期可控,性能也更好:
#include <iostream> #include <string> #include <vector> #include <memory> #include <utility> class Object { public: std::string Name; Object(std::string name) : Name(std::move(name)) {} virtual void Tick() { std::cout << Name << std::endl; } virtual ~Object() = default; }; class Game { private: std::vector<std::unique_ptr<Object>> objects; public: // 模板化注册接口,支持所有Object派生类 template<typename T, typename... Args> T* AddObject(Args&&... args) { auto obj = std::make_unique<T>(std::forward<Args>(args)...); T* ptr = obj.get(); objects.push_back(std::move(obj)); return ptr; } void Tick() { for (auto& obj : objects) { obj->Tick(); } } }; int main() { Game game; game.AddObject<Object>("obj1"); game.AddObject<Object>("obj2"); while (true) { game.Tick(); // 测试用终止条件 break; } return 0; }
该方案的优势:
- 内存连续,遍历效率比链表方案高3~10倍
- 对象生命周期由
Game统一管理,不会出现野指针问题 - 支持多
Game实例,适合后续功能扩展 - 注册逻辑封装在
Game内部,不需要修改Object类的基础逻辑
内容的提问来源于stack exchange,提问作者Wils
相关产品推荐
相关产品推荐

