Рассмотрим следующие два класса:
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 можно преобразовать с помощью второго конструктора 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 оптимизация возвращаемого значения работает. Есть два вызова:
- База (целое число)
- ~ База ()
Однако тут нечего выигрывать, когда Derived-объект нужен в main. Для «upcast» требуется другая пара конструктор/деструктор.
В Случае 2 оптимизация возвращаемого значения не работает. Здесь создаются и уничтожаются два объекта:
- Base(int) //Создать временное
- ~Base() //Уничтожить временно
- Base(const Base&) //через Derived(const Base&)
- ~Base() //через ~Derived()
Теперь мне кажется, что у меня есть три противоречивых требования:
- Я хотел бы избежать накладных расходов на создание временного объекта (поскольку создание и уничтожение объекта довольно затратно в классе Base)
- В main мне нужен Производный-объект вместо Base-объекта для работы.
Очевидно, что бесплатного обеда здесь не бывает. Но я мог что-то упустить. Итак, мой вопрос: есть ли способ объединить эти требования? Или у кого-то был подобный опыт?
Примечание: мне известен тот факт, что производный объект "upcast" (const Base и другие) может дать сбой во время выполнения (об этом позаботились). Поскольку код в порядке на синтаксическом уровне, я думаю, это не причина, по которой компилятор избегает RVO.
Base
? Я не думаю, что это законно -b
иd1
являются отдельными объектами, и подобъект базового классаd1
должен быть создан изb
. Исключение конструктора-копирования допускает исключение только временных объектов, а не переменных. [Редактировать: о, подождите, вы имеете в виду, что он есть, но вы его не указали? требуется другая пара ctor/dtor. Я бы сказал, что RVO работает, но, как вы видели, он не делает то, что вам нужно.] - person Steve Jessop   schedule 24.04.2011