C++中unique_ptr性能优于原始指针?基准测试异常结果求解
问题原因分析
- 最核心的问题是基准测试没有添加防止编译器过度优化的标记:你测试中的两个指针变量都是局部变量,没有任何后续使用,编译器在高优化等级(比如O2、O3)下会尝试消除无副作用的代码。标准库的
std::unique_ptr实现是编译器熟知的模板逻辑,更容易被判定为无副作用直接消除整个new+构造+析构+delete流程,而手动实现的raw指针+自定义deleter的逻辑,编译器可能没有完全消除,最终出现raw指针测试耗时更长的错误结果。你需要使用Google Benchmark提供的benchmark::DoNotOptimize标记指针,防止编译器将相关操作优化掉。 - 测试对象太小,开销被堆分配淹没:你测试中分配的是仅4字节的int类型,
new/delete的堆操作开销远大于指针本身的管理开销,测试实际统计的是堆分配速度,而非两种指针的操作差异。 - 无状态自定义deleter的优化差异:你定义的
deleter是空类,没有任何成员变量,std::unique_ptr会触发空基类优化,不需要额外存储deleter对象,构造、析构过程的所有逻辑都会在编译期展开,和直接调用delete没有任何运行时差异,理论上两段代码的开销完全一致。
修正后的测试代码示例
struct deleter { template<typename T> void operator()(T* ptr) { delete ptr; } }; void BM_rawPtr(benchmark::State& state) { deleter d; for (auto _ : state) { int* p = new int(0); benchmark::DoNotOptimize(p); // 防止p被优化消除 d(p); } state.SetItemsProcessed(state.iterations()); } void BM_uniquePtr(benchmark::State& state) { deleter d; for (auto _ : state) { std::unique_ptr<int, deleter> ptr(new int(0), d); benchmark::DoNotOptimize(ptr); // 防止ptr被优化消除 } state.SetItemsProcessed(state.iterations()); } BENCHMARK(BM_rawPtr); BENCHMARK(BM_uniquePtr); BENCHMARK_MAIN();
修正后在同等级别优化下重新测试,两段代码的耗时会基本一致,符合unique_ptr是零开销抽象的特性,不会出现比raw指针更快的异常结果。
内容的提问来源于stack exchange,提问作者Eduard Rostomyan
相关产品推荐
相关产品推荐

