У меня есть фабричная функция, которая возвращает контейнер STL:
const std::vector<int> f(...) {
std::vector<int> retval;
return retval;
}
Я думаю, это нормально, чтобы определить экземпляр stl следующим образом (без ошибок):
const std::vector<int> stl_instance(f(...));
Но так ли это эффективно?
Является ли временный объект STL непосредственно назначенным stl_instance
?
Возвращение const rvalue является антишаблоном в C ++ 11. Сначала рассмотрим возврат неконстантных значений:
std::vector<int> f(int n)
{
return std::vector<int>(n);
}
int main()
{
std::vector<int> v;
v = f(3);
}
В C ++ 98/03 этот код будет попадать в кучу как минимум дважды:
Если ваш компилятор не применяет RVO, вы получаете 3 выделения кучи.
В C ++ 11 вы получаете только 1 выделение кучи: чтобы создать вектор внутри f
, Это происходит независимо от RVO. Причина в том, что все контейнеры STL имеют конструкторы перемещения и операторы присваивания перемещения, которые имеют подписи
vector( vector&& other );
vector& operator=( vector&& other );
Rvalue ссылки &&
переместит ресурсы из вашей функции создания прямо в место назначения. Тем не менее, ваш код имеет подпись
const std::vector<int> f(int n)
{
return std::vector<int>(n);
}
отключит семантику перемещения, потому что T&& (то есть аргумент конструктора перемещения и оператора присваивания) не будет привязываться к параметру const rvalue (то есть к возвращаемому значению вашей функции). Это эффективно заставляет ваш код работать как в C ++ 98/03 (то есть с 2 или 3 выделениями кучи).
Это прекрасный и юридический код.
Компилятор позаботится о необходимых оптимизациях (если может) через копию elision.
Временный f(...)
гарантированно проживет, по крайней мере, до конца выражения. Обратите внимание, что выражения заканчиваются сразу после возврата из stl_instance(f(...))
, точнее ;
(точка с запятой в конце вызова). Так что это совершенно верно.
Стандарт C ++ 03 §12.2 / 3:
Временные объекты уничтожаются как последний шаг в оценке полного выражения (1.9), которое (лексически) содержит точку, где они были созданы.