Существует шаблон C ++ в стиле RAII, который реализует владение на основе области путем создания класса, который не имеет члена, и полагается на конструктор и деструктор класса (и тот факт, что деструктор автоматически вызывается при возврате функции). Например, стандарт std::lock_guard
реализует этот шаблон.
Я программирую микроконтроллер ARF Cortex-M EFM32 и придумала этот класс, который использует похожий стиль:
#include <em_int.h>
class InterruptGuard final {
public:
explicit inline InterruptGuard() {
INT_Disable();
}
InterruptGuard(const InterruptGuard &other) = delete;
InterruptGuard(const InterruptGuard &&other) = delete;
inline ~InterruptGuard() {
INT_Enable();
}
InterruptGuard &operator=(const InterruptGuard &other) = delete;
InterruptGuard &operator=(const InterruptGuard &&other) = delete;
};
Поэтому, если я хочу отключить прерывания внутри функции с помощью нескольких операторов возврата, я могу убедиться, что они будут включены повторно, и я не буду беспокоиться об их явном включении при каждом операторе возврата.
Обратите внимание INT_Enable
а также INT_Disable
функции реализовать счетчик так INT_Enable
будет делать правильные вещи и включать прерывания только тогда, когда они действительно должны быть включены. Так что этот класс должен быть правильно вложенным.
void func() {
InterruptGuard guard;
// ...
}
Мой вопрос:
Когда я использую этот шаблон, собирается ли компилятор делать «правильные вещи» здесь и оптимизировать объект (так, чтобы этот класс фактически не потреблял память) и просто вставлять INT_Enable
а также INT_Disable
вызовы функции, которая использует InterruptGuard
учебный класс?
составление с g++ -std=c++1y -O3 -Werror -Wextra
(gcc версия 5.3.0) этот код:
#include <cstdio>
class InterruptGuard final {
public:
explicit inline InterruptGuard() {
printf("enable\n");
}
InterruptGuard(const InterruptGuard &other) = delete;
InterruptGuard(const InterruptGuard &&other) = delete;
inline ~InterruptGuard() {
printf("disable\n");
}
InterruptGuard &operator=(const InterruptGuard &other) = delete;
InterruptGuard &operator=(const InterruptGuard &&other) = delete;
};
int main()
{
InterruptGuard i;
}
и этот код:
#include <cstdio>
int main()
{
printf("enable\n");
printf("disable\n");
}
дает одинаковую сборку в обоих случаях:
.LC0:
.string "enable".LC1:
.string "disable"main:
subq $8, %rsp
movl $.LC0, %edi
call puts
movl $.LC1, %edi
call puts
xorl %eax, %eax
addq $8, %rsp
ret
Других решений пока нет …