C++中存储选中对象引用的最佳方案 适配低延迟解析场景
C++ 存储多类型对象引用的低延迟实现方案
方案1:预绑定访问器(最匹配你的场景,零分支开销)
你提到解析过程中就可以确定要操作的对象和对应字段,直接在解析阶段把字段访问逻辑绑定成可调用对象即可,后续完全不需要任何分支判断,延迟最低:
#include <iostream> #include <functional> using namespace std; class A{ public: int a; A(int b):a(b){} }; class B{ public: int b; B(int a):b(a){} }; int main() { A a(1); B b(2); // 解析阶段直接绑定对应字段的访问逻辑,读场景可直接用function<int()> function<int*()> x = [&a](){return &a.a;}; cout << *x() << endl; // 输出1 x = [&b](){return &b.b;}; cout << *x() << endl; // 输出2 return 0; }
调用时完全没有类型判断开销,没有额外内存分配,完全符合低延迟要求。
方案2:手动实现标签联合(零额外开销,支持保留类型信息)
如果需要保留原始类型信息,后续可能有其他扩展操作,用标签联合方案,运行时开销趋近于0,比标准库实现更轻量:
#include <iostream> using namespace std; class A{ public: int a; A(int b):a(b){} }; class B{ public: int b; B(int a):b(a){} }; struct TaggedPtr { enum Type {A_TYPE, B_TYPE} type; union { A* a_ptr; B* b_ptr; }; // 封装访问方法对外隐藏分支,业务层不需要写switch case int get() const { return type == A_TYPE ? a_ptr->a : b_ptr->b; } }; int main() { A a(1); B b(2); TaggedPtr x{TaggedPtr::A_TYPE, .a_ptr = &a}; cout << x.get() << endl; // 输出1 x = {TaggedPtr::B_TYPE, .b_ptr = &b}; cout << x.get() << endl; // 输出2 return 0; }
所有逻辑编译期确定,运行时只有一次极快的跳转判断,无虚函数、无动态内存开销,适合极限低延迟场景。
方案3:std::variant 标准方案(代码简洁易维护)
C++17及以上版本可以直接用标准库的std::variant,代码更简洁维护成本低,std::visit的开销几乎可以忽略,适合类型后续可能扩展的场景:
#include <iostream> #include <variant> using namespace std; class A{ public: int a; A(int b):a(b){} }; class B{ public: int b; B(int a):b(a){} }; struct Visitor { int operator()(A* a) const { return a->a; } int operator()(B* b) const { return b->b; } }; int main() { A a(1); B b(2); variant<A*, B*> x = &a; cout << visit(Visitor{}, x) << endl; // 输出1 x = &b; cout << visit(Visitor{}, x) << endl; // 输出2 return 0; }
标准库实现已经做了极致优化,大部分场景下和手动实现的标签联合性能一致,不需要手动处理union的内存安全问题。
内容的提问来源于stack exchange,提问作者DEEPANSH NAGARIA
相关产品推荐
相关产品推荐

