一、为什么需要它们
编译器非常聪明,会优化掉"看起来没用的代码":
void test_sine() {
double x = 0.0;
for (int i = 0; i < 100000; i++) {
x = sin(x); // 编译器发现 x 没有后续使用 → 整个循环被删掉!
}
}
// 如果你用 benchmark 测试这个函数,测出来时间 ≈ 0ns
// 因为编译器把整个循环优化掉了
二、正确用法
static void BM_Sine(benchmark::State& state) {
double x = 0.0;
for (auto _ : state) {
x = sin(x);
// 告诉编译器:这个值后续会被使用,不能删
benchmark::DoNotOptimize(x);
}
// 最终把 x 输出,也是告诉编译器"x 确实被用了"
std::cout << x << std::endl;
}
static void BM_Memcpy(benchmark::State& state) {
char src[1024] = {}, dst[1024] = {};
for (auto _ : state) {
memcpy(dst, src, 1024);
// 告诉编译器:dst 的内容被"外部"使用了
benchmark::ClobberMemory();
}
}
// 对比没有 ClobberMemory 的版本——编译器可能会把 memcpy 优化掉
static void BM_Memcpy_Wrong(benchmark::State& state) {
char src[1024] = {}, dst[1024] = {};
for (auto _ : state) {
memcpy(dst, src, 1024);
// dst 后续没被使用 → 编译器可能优化掉 memcpy
// 测出来的时间 ≈ 0ns
}
}