通用类型向量性能优化:实现媲美std::vector的动态类型容器
优化运行时类型确定的Vector类性能方案
针对你遇到的问题——既要支持运行时动态确定预定义类型,又要让Vector性能追平std::vector,同时避免重复编写switch-case,以下是几个实用的优化思路:
1. 封装批量操作的类型分发逻辑
将switch-case的类型判断从单元素操作中剥离,统一放到批量操作的入口处,循环内部完全消除分支开销,同时复用代码避免重复编写switch:
// 预定义所有支持类型的批量赋值实现 template<typename T> void batchAssign(void* data, size_t startIdx, size_t count, const void* value) { T* arr = static_cast<T*>(data); const T& val = *static_cast<const T*>(value); // 循环内无分支,性能与std::vector直接赋值一致 for (size_t i = startIdx; i < startIdx + count; ++i) { arr[i] = val; } } // 定义批量操作函数指针类型 using BatchAssignFunc = void(*)(void*, size_t, size_t, const void*); class MyVector { private: void* m_data; size_t m_typeIndex; // 运行时标识当前类型的索引 static const BatchAssignFunc s_assignTable[]; // 类型到批量函数的映射表 public: // 批量赋值接口,仅在入口做一次类型判断 void setValueRange(size_t start, size_t count, const void* val) { s_assignTable[m_typeIndex](m_data, start, count, val); } // 单元素赋值复用批量逻辑,避免重复写switch void setValue(size_t idx, const void* val) { setValueRange(idx, 1, val); } }; // 初始化映射表(假设支持int/float/double三种类型) const BatchAssignFunc MyVector::s_assignTable[] = { batchAssign<int>, batchAssign<float>, batchAssign<double> };
这种方案仅在批量操作入口做一次类型查找,循环内完全是原生类型的赋值逻辑,性能可以和std::vector持平,同时单元素操作也无需额外编写switch。
2. 用模板元编程自动生成类型分发代码
如果需要支持多种类型且不想手动维护switch分支,可以借助模板元编程编译期生成类型分发逻辑,只需要维护一个类型列表即可:
#include <tuple> #include <utility> // 预定义支持的类型列表,新增类型只需修改这里 using SupportedTypes = std::tuple<int, float, double, std::string>; // 编译期生成switch-case分支的分发器 template<typename Func> void dispatchByType(size_t typeIdx, Func&& func) { using Seq = std::make_index_sequence<std::tuple_size_v<SupportedTypes>>; auto dispatch = [&]<size_t... Idx>(std::index_sequence<Idx...>) { ((typeIdx == Idx ? (func.template operator()<std::tuple_element_t<Idx, SupportedTypes>>(), true) : false) || ...); }; dispatch(Seq{}); } class MyVector { private: void* m_data; size_t m_typeIndex; public: void setValueRange(size_t start, size_t count, const void* val) { dispatchByType(m_typeIndex, [&]<typename T>() { T* arr = static_cast<T*>(m_data); const T& value = *static_cast<const T*>(val); for (size_t i = start; i < start + count; ++i) { arr[i] = value; } }); } };
这种方案不需要手动编写switch-case,新增类型仅需修改SupportedTypes元组,编译期会自动生成所有类型分支,既保证性能又减少代码冗余。
3. 补充性能优化细节
- 确保内存布局与
std::vector一致:使用连续内存存储元素,避免额外的内存间接访问,保证缓存友好性。 - 禁用不必要的运行时检查:如果Vector的类型是固定的(一旦构造就不再改变),可以将类型索引的判断逻辑放到构造时完成,后续操作直接绑定到对应类型的实现,进一步减少开销。
内容的提问来源于stack exchange,提问作者Awen
相关产品推荐
相关产品推荐

