Если ваш конструктор и деструктор PerfEventBlock
выполняют системный вызов, то компилятор не сможет доказать, что он не имеет видимых побочных эффектов.Тем не менее, он все еще может (теоретически) переупорядочить ваш прерывистый код до или после них, при условии, что он может доказать, что это не изменит наблюдаемого поведения с точки зрения абстрактной машины.См. Также, например, здесь .
Пример:
void inc(int& a) { ++a; }
void foo();
int bar()
{
int a = 1;
foo();
inc(a);
foo();
return a;
}
https://godbolt.org/z/gOr7aU
Компилятор не знает, что foo()
делает такдолжен предположить, что есть наблюдаемые побочные эффекты.Тем не менее, вы можете увидеть в сборке, что inc
настолько тривиален, что компилятор вставил (и свернул).Между двумя побочными эффектами нет необходимости выполнять все, что связано с inc(a)
, поскольку само по себе inc
не имеет никакого внешнего наблюдаемого эффекта.
Таким образом, возможно, что компилятор переместит код, который вы хотитепрофиль между конструктором и деструктором PerfEventBlock
.На самом деле, при оптимизации во время компоновки эта опция может остаться в таблице дальше, чем вы думаете (вызов функции в другом модуле компиляции - например, foo()
здесь - может быть непрозрачным для компилятора, но не для компоновщика).