2016-04-24 1 views
2

Существует образец шаблона C++ в стиле RAII, который реализует право собственности на основе объектов, создавая класс, который не имеет члена и полагается на конструктор и деструктор класса (и тот факт, что деструктор автоматически вызывается при возврате функции). Например, стандарт std::lock_guard реализует этот шаблон.Является ли сам объект оптимизирован, когда я использую этот шаблон в стиле RAII?

Я программирование EFM32 ARM Cortex-M микроконтроллеров и придумал этот класс, который использует подобный стиль:

#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 функции implement a counter так INT_Enable будет делать правильные вещи, и только разрешить прерывания, когда они действительно должны быть включены. Таким образом, этот класс должен быть надлежащим образом вложенным.

void func() { 
    InterruptGuard guard; 

    // ... 
} 

Мой вопрос:

Когда я использую этот шаблон, это компилятор собирается делать «правильные вещи» здесь и оптимизировать вне объекта (так что память не потреблено этого класса) и просто введите INT_Enable и INT_Disable вызовы функции, которая использует класс InterruptGuard?

+1

Вероятно , Единственный способ сказать наверняка - посмотреть на сгенерированный код. –

+0

На самом деле нет памяти, занятой 'InterruptGuard', поэтому что нужно оптимизировать? –

+0

@ πάνταῥεῖ 'Почему? sizeof (InterruptGuard) 'должен быть отличным от нуля, и вы можете взять адрес' guard'. –

ответ

5

Compiling с 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 
+1

Вот [рука версия] (https: // godbolt. org/g/GiHFR4) при использовании OP. Обратите внимание, что этот RAII не контролирует, когда прерывания включены/отключены, и позволяет компилятору понять это. Во многих случаях это может увеличить задержку прерывания. RAII отлично подходит для ухода, где время выполнения не имеет значения. Вы можете решить эту проблему, если хотите, чтобы прерывания были отключены; объект должен существовать только для блока. –

Смежные вопросы