Автоматическое уничтожение объекта
Гарантируется ли уничтожение автоматических объектов (объектов, созданных в стеке) не раньше, чем они выйдут из области видимости?
Чтобы уточнить:
#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 требуется.