Во-первых, давайте посмотрим на вещи, которые вступают в игру здесь:
(a) Продление срока действия временного , когда он используется для инициализации ссылки - об этом я узнал в этой публикации Андрея Анександреску. Опять же, это странно, но полезно:
class Foo { ... }
Foo GetFoo() { return Foo(); } // returning temporary
void UseGetFoo()
{
Foo const & foo = GetFoo();
// ... rock'n'roll ...
foo.StillHere();
}
Правило гласит, что когда ссылка инициализируется с помощью временного объекта, срок его действия продлевается до тех пор, пока ссылка не выйдет из области видимости. ( этот ответ цитирует канон)
(b) Оптимизация возвращаемого значения - ( wikipedia ) - две копии локально -> возвращаемое значение -> локально может быть опущено при определенных обстоятельствах , Это удивительное правило, поскольку оно позволяет компилятору изменять наблюдаемое поведение, но полезно.
Вот, пожалуйста. C ++ - странно, но полезно.
Итак, глядя на ваши сценарии
Сценарий A: вы возвращаете временный объект и связываете его со ссылкой - срок жизни временного объекта увеличивается до времени жизни l_Foo.
Обратите внимание, что это не будет работать, если GetFoo
вернет ссылку, а не временную.
Сценарий B: Работает, за исключением того, что он вызывает цикл Construct-Construct-Copy-Cycle (который может быть намного дороже, чем одиночная конструкция), и проблема, о которой вы упоминаете требующий конструктор по умолчанию.
Я бы не использовал этот шаблон для создания объекта - только для изменения существующего.
Сценарий C: Копии временных данных могут быть опущены компилятором (как правило RVO). К сожалению, нет никакой гарантии - но современные компиляторы реализуют RVO.
Rvalue ссылки в C ++ 0x позволяет Foo реализовать конструктор похищения ресурсов, который не только гарантирует подавление копий, но и пригодится в других сценариях.
(Я сомневаюсь, что есть компилятор, который реализует ссылки на rvalue, но не RVO. Однако есть сценарии, в которых RVO не может войти.)
Подобный вопрос требует упоминания умных указателей, таких как shared_ptr
и unique_ptr
(последний является "безопасным" auto_ptr
). Они также находятся в C ++ 0x . Они предоставляют альтернативный шаблон для функций, создающих объекты.