Автоматическое уничтожение объекта

Гарантируется ли уничтожение автоматических объектов (объектов, созданных в стеке) не раньше, чем они выйдут из области видимости?

Чтобы уточнить:

#include <iostream>

class A {
  public:
    A() {
      std::cout << "1";
    }
    ~A() {
      std::cout << "3";
    }
};

void test123() {
  A a;
  std::cout << "2";
}

Печатать "2", a больше не требуется, поэтому теоретически компилятор может попытаться оптимизировать и уничтожить a как только это больше не нужно.

Могу ли я полагаться на вышеуказанную функцию всегда печатать 123?

3 ответа

Решение

Порядок уничтожения стековых объектов строго определен - они выполняются в порядке, обратном объявлению, когда вы покидаете область видимости (либо выполняя выход из конца {}или returnили исключением). Итак, вы всегда увидите 123 там.

Однако обратите внимание, что оптимизация компилятора регулируется правилом "как будто". Другими словами, компилятор может уничтожить объект на ранней стадии, если результирующая программа ведет себя так, как если бы она была уничтожена в обычное время. В этом случае, поскольку вы делаете вывод, компилятор должен запланировать вывод в нужное время. Однако, если у вас было, например, deleteЕсли указатель на примитивный тип, и компилятор может доказать, что нет других выдающихся указателей на это значение, он может, в принципе, переместить это delete ранее. Ключ в том, что ни одна соответствующая программа не способна заметить эту оптимизацию.

Стандарт определяет, что правильным поведением для этого кода является печать "123". Компиляторам разрешено изменять код столько раз, сколько они хотят, сохраняя при этом ту же семантику (как если бы правило), и переупорядочение кода здесь изменит семантику, поэтому совместимый компилятор не может это делать.

Конструкторы могут иметь побочные эффекты. Например, они могут реализовать мьютекс, т.е. конструктор блокирует, а десктуктор разблокирует мьютекс. Поэтому 123 требуется.

Другие вопросы по тегам