You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 15:45:08