Когда гарантируется применение RVO / применяется ли он с компиляторами C ++ 20? - PullRequest
6 голосов
/ 07 октября 2019

В рекомендациях по ядру C ++ говорится, что

F.20: Для «выходных» выходных значений предпочитайте возвращаемые значения выходным параметрам

Но затем выдает следующее исключение:

struct Package {      // exceptional case: expensive-to-move object
    char header[16];
    char load[2024 - 16];
};

Package fill();       // Bad: large return value
void fill(Package&);  // OK

Разве это не должно быть случаем, когда оптимизация возвращаемого значения вступает в силу? Предотвращается ли RVO в этом случае? Или все же не так эффективно, как передача по ссылке? Или это то, что некоторым компиляторам не удается это сделать?

В более общем случае, когда я должен полагаться на компилятор, оптимизирующий возвращаемые значения так же эффективно, как метод передачи по ссылке?

Ответы [ 2 ]

4 голосов
/ 07 октября 2019

«Простой» RVO (т. Е. Возвращение prvalue или «временный» на обычном языке) гарантируется в C ++ 17 и хорошо поддерживается даже до этого.

NRVO (т. Е. Возвращение локальной переменной) может быть привередливым и не гарантируется, и если это не будет выполнено, вместо этого вы получите ход. Если ваш ход дорогостоящий, вы можете избежать этого.

В этом примере есть неплохой шанс, что fill нужно использовать последний.

4 голосов
/ 07 октября 2019

Или все же не так эффективно, как передача по ссылке?

Если применяется RVO, то одинаково эффективно возвращать значение, как и использовать выходную ссылку.

Предотвращается ли в этом случае RVO?

Нет. «Большой» не мешает объекту быть RVO'd.

Когда гарантируется применение RVO / применяется к компиляторам C ++ 20

Случайгде это не применимо:

... Оператор return может включать вызов конструктора для выполнения копирования или перемещения операнда, если он не является prvalue или его тип отличается оттип возврата функции.

Таким образом, зависит от реализации функции, гарантировано ли копирование-исключение.

В руководствах действительно не объясняется почему рекомендация должна соблюдаться.

Обратите внимание, что в исключении написано:

Исключения

Если тип дорог для перемещения (например, * 1035)*), рассмотрите возможность размещения его в бесплатном хранилище и возврата дескриптора (например, unique_ptr) или передачи его в ссылку на неконстантный целевой объект для заполнения (для использования в качестве выходного параметра).

Подсвеченное предложение в мак-исключенииУ меня больше смысла. Это дает понять, что объект слишком большой для стека, и, таким образом, уменьшает вероятность переполнения стека.

...