Рассмотрим следующие два класса:
class Base
{
Base(const Base& other) {...} // relatively expensive operations here...
Base(int i) {...} // ...here,
virtual ~Base() {...} // ...and here
...
};
class Derived : public Base
{
...
Derived(const Base& other) :Base(other) {...} // some typechecking in here
virtual ~Derived() {}
...
};
Это означает, что База может быть "повышена" с помощью второго конструктора из Производная .
Теперь рассмотрим следующий код:
Base getBase()
{
int id = ...
return Base(id);
}
...
int main()
{
Base b = getBase(); // CASE 1
Derived d1(b); // "upcast"
Derived d2 = getBase(); // CASE 2
...
}
Я использую VS2008 с включенными оптимизациями (/ Ox / Ob2 / Oi / Ot). Я проверил вызовы конструкторов и деструкторов на консольном выводе:
В Случай 1 работает оптимизация возвращаемого значения. Есть два вызова:
- Base (INT)
- ~ Base ()
Однако здесь нечего выиграть, когда Derived -объект необходим в main . Для "upcast" требуется другая пара конструктор / деструктор.
В Случай 2 Оптимизация возвращаемого значения не работает. Здесь создаются и уничтожаются два объекта:
- Base (int) // Создать временную
- ~ Base () // Уничтожить временно
- База (константная база &) // через производную (константная база &)
- ~ Base () // через ~ Derived ()
Теперь мне кажется, что у меня есть три противоречивых требования:
- Я бы хотел избежать накладных расходов на создание временного объекта (поскольку создание и уничтожение объекта довольно дорого в классе Base )
- В main мне нужен Derived -объект вместо Base -объекта для работы с.
Очевидно, здесь нет бесплатного обеда. Но я мог что-то пропустить. Итак, мой вопрос: есть ли способ объединить эти требования? Или у кого-нибудь был подобный опыт?
Sidenote: Мне известен тот факт, что производный "upcast" (const Base и другие) может завершиться ошибкой во время выполнения (об этом позаботились). Поскольку на синтаксическом уровне код в порядке, я думаю, что это не причина для компилятора избегать RVO.