Что происходит:
На стороне вызывающего абонента, возврат предусмотрен слот, который может содержать результат, что означает, что абонент предоставляет памяти для переменного типа std::vector<int>
. Он ожидает, что вызываемый метод построит значение и сам отвечает за вызов деструктора, когда результат больше не используется и освобождает память (при необходимости он, вероятно, просто живет в стеке).
Вызванная функция (которая может жить в другой единице трансляции!) Будет, без NRVO, так это:
- Обеспечить слот памяти для
ret
.
- Построить локальную переменную
ret
в этом слоте памяти.
- Сделайте нужный материал ...
- Копировать-построить возвращаемое значение в предоставленном слоте памяти путем копирования
ret
.
- Звонок
ret
Деструктор.
Теперь, с NRVO, решение для оптимизации, это может быть сделано в блоке перевода вызываемой функции. Он преобразует вышеуказанное значение в:
- Построить
ret
в память обратного хода метода.
- Сделайте что-нибудь ...
Нет необходимости делать что-нибудь еще, как память принадлежит и деструктор вызывается вызывающим абонентом и потому, что оптимизация является прозрачным для вызывающего абонента :)
Это, конечно, не может устранить присваивание в v
в вашем примере. Если вы сохраняете результат в другой переменной, например.
std::vector<int> w = f(v);
NRVO построит ret
непосредственно в память w
«ы (как это будет принят в качестве слота возврата к f
).
Существует две различные формы оптимизации возврата: копия из 'ret' во временное, чтобы вернуться из' f', а копия из этого временного в 'v'. Только первый разрешен здесь. – dyp
Возможно, компилятор будет оптимизировать всю линию заполнения – OllieB
@OllieB Возможно, но это был просто простой пример, который я составил. –