Почему деструктор производного класса вызывается по константной ссылке на базовый класс?
В ответе GMan здесь, деструктор restore_base
класс не virtual
Поэтому я продолжаю задаваться вопросом, как именно это работает. Обычно вы ожидаете деструктора restorer_base
выполняется только после того, как объект выходит из области видимости, но кажется, что производная restorer_holder
деструктор действительно называется. Кто-нибудь хочет меня просветить?
1 ответ
Стандартный случай, когда вам нужен виртуальный деструктор
void foo()
{
scoped_ptr<Base> obj = factory_returns_a_Derived();
// ... use 'obj' here ...
}
И стандартный случай, когда вы не
void foo()
{
Derived obj;
// ... use 'obj' here ...
}
Код GMan делает что-то более хитрое, что оказывается эквивалентным второму случаю:
void foo()
{
Base& obj = Derived();
// ... use 'obj' here ...
}
obj
голая ссылка; как правило, это не будет вызывать деструкторы вообще. Но он инициализируется из анонимного временного объекта, чей статический тип - известный компилятору - Derived
, Когда время жизни этого объекта заканчивается, компилятор вызовет Derived
деструктор. Обычно анонимный временный объект умирает в конце выражения, которое его создало, но есть особый случай для временных инициализаций ссылки: они живут до тех пор, пока сама ссылка не умирает, что и является концом области действия. Таким образом, вы получаете псевдо-scoped_ptr
поведение, и вам не нужен виртуальный деструктор.
РЕДАКТИРОВАТЬ: так как это теперь подошло дважды: ссылка не должна быть const
для применения этого специального правила. С +98 [класс.времен]/5:
Второй контекст [в котором временный объект не уничтожается в конце полного выражения] - это когда ссылка связана с временным. Временный объект, к которому привязана ссылка, или временный объект, являющийся полным объектом для подобъекта, к которому привязан временный объект, сохраняется в течение всего времени существования ссылки...
Акцент мой. Там нет упоминания о const
на этом языке, поэтому ссылка не должна быть const
,
РЕДАКТИРОВАНИЕ 2: Другие правила в стандарте запрещают создание неконстантных ссылок на временные объекты, которые не являются lvalues. Я подозреваю, что по крайней мере некоторые временные объекты являются lvalues, но я не знаю наверняка. Несмотря на это, это не влияет на это правило. Формально все равно было бы верно, что неконстантные ссылки на временные объекты продлевают срок их службы, даже если никакая строго соответствующая программа на C++ не может создать такую ссылку. Это может показаться смешным, но вы должны читать это буквально и педантично. Каждое слово имеет значение, каждое слово, которого там нет, имеет значение.