Рассмотрим следующий код (минимальная версия):
#include <iostream>
struct Base
{
virtual ~Base() {}
virtual void test() const { std::cout << "base"; }
};
struct Derived : public Base
{
void test() const { std::cout << "derived"; }
};
struct Composite
{
const Derived &ref;
Composite(const Derived &ref) : ref(ref) {}
void testRef() const { ref.test(); }
};
int main()
{
Composite c((Derived()));
c.testRef();
}
Это на самом деле создает «базу» при использовании последней версии MinGW g ++! Это ошибка компилятора или я что-то упустил? Может кто-нибудь проверить это в VS, пожалуйста?
Я считаю себя опытным программистом C ++, постоянно использующим полиморфизм, основанные на стеке ссылки, временные объекты (стандарт C ++ 12.2) и т. Д. Поэтому я знаю, что следует применять продление времени жизни.
Это происходит только при определении деструктора в Base (виртуального или нет) и использовании временного, т.е. е. следующее использование производит «производный»:
int main()
{
Derived d;
Composite c(d);
c.testRef();
}
Composite c((Derived()));
Эта строка создает временный объект типа Derived
, передает его конструктору c
, а затем уничтожает временный объект. После этого все ставки выключены.
Composite c((Derived()));
Когда вы определили деструктор Base и программу, оставьте конструктор Composite, деструктор Derived и Base выполненным. Чтобы избежать ошибки при вызове виртуальной функции Base в деструкторе Base (теперь Derived уничтожен), программа перемещает точку виртуальной функции (которая является просто адресом объекта этого тестового кода) из таблицы виртуальных функций, производной от база. Если вы не определяете деструктор, то ничего не делаете. Адрес по-прежнему указывает на таблицу производных виртуальных функций.
c.testRef();
Ссылка по-прежнему получает адрес объекта и адрес таблицы виртуальных функций и вызывает функцию в таблице. Так что разница существует.
Я тестирую в VC 8.0 и проверяю память. Это происходит потому, что некоторые виды «счастливчики».