C ++ деструктор и порядок вызова функций - PullRequest
13 голосов
/ 04 февраля 2010

Предположим, у меня есть следующий фрагмент кода:

Foo foo;
....
return bar();

Теперь, гарантирует ли стандарт C ++, что bar () будет вызываться до foo :: ~ Foo ()? Или это выбор компилятора / реализации?

Спасибо!

Ответы [ 5 ]

15 голосов
/ 04 февраля 2010

Это гарантированное поведение. Фактическое выполнение развернуто следующим образом:

0: enter block (scope)
1: Foo::Foo()
2. evaluation of bar(); as expression in return statement
3. save result of the expression as value returned from function
4. finalize return statement to leave function to its caller (request exit from current scope)
5: exit block (scope) with call to  Foo::~Foo()

Вот некоторые ссылки из стандарта:

  • Что гарантирует выполнение программы, обычно

1,9 Выполнение программы

10 Экземпляр каждого объекта с автоматической продолжительностью хранения (3.7.2) связано с каждой записью в его блок.

  • foo имеет длительность автоматического хранения и:

3.7.2 Срок хранения в автоматическом режиме

1 Локальные объекты явно объявлены auto или register или не объявлены явно статические или внешние имеют автоматическую продолжительность хранения. Хранение для эти объекты сохраняются до выхода из блока, в котором они созданы.

  • Каков фактический эффект от оператора возврата

6.6.3 Оператор возврата

2 (...) значение выражения возвращается вызывающей функции

и

6.6 Операторы перехода (возврат относится к операторам перехода)

2 При выходе из области (хотя и выполненной) деструкторы (12.4) вызываются для всех построенные объекты с автоматическим сроком хранения (3.7.2)

  • Что гарантирует эффект

6.7 Заявление о декларации

2 Переменные с автоматической продолжительностью хранения, объявленные в блоке: уничтожен на выходе из блока

и

12.4 Деструкторы

10 Деструкторы вызываются неявно (1) для построенного объект со статической продолжительностью хранения (3.7.1) при завершении программы (3.6.3), (2) для построенного объекта с автоматической продолжительностью хранения (3.7.2) когда блок, в котором объект создан, выходы (6.7)

Нелегко понять отдельные детали формы идеи, разбросанные по всему стандарту C ++. Надеемся, что краткий обзор поможет вам сделать такой анализ самостоятельно.

7 голосов
/ 04 февраля 2010

Да, bar () будет вызываться перед деструктором foo.

Стандарт гласит: 6.6: «При выходе из области видимости (как бы то ни было) деструкторы (12.4) вызывается для всех построенных объектов с автоматическим сроком хранения (3.7.2) (именованные объекты или временные объекты), которые объявлены в этой области, в обратном порядке их объявления. "

Область действия не остается до тех пор, пока оператор возврата не будет завершен.

5 голосов
/ 04 февраля 2010

Результат вызова bar () должен быть оценен до очистки стекового кадра, содержащего Foo, поэтому да, bar () будет вызываться перед Foo :: ~ Foo ().

3 голосов
/ 04 февраля 2010

Объекты разрушаются при выходе из области видимости.

return покидает область, но не может вернуться, пока не выполнит bar(). Ergo, bar() называется.

2 голосов
/ 04 февраля 2010

Только подумайте, а что, если это было return bar(foo);? Это просто имеет для работы, и было бы глупо, если бы порядок уничтожения был другим в зависимости от того, передаете ли вы это в качестве аргумента или нет.

...