Разрешение копирования автоматической переменной для возврата - PullRequest
4 голосов
/ 24 апреля 2011

Мне интересно, если в C ++ 0x "12.8 Копирование и перемещение объектов класса [class.copy] параграф 31" , когда copy elision происходит, точно:

При соблюдении определенных критериев реализация может опустить конструкцию копирования / перемещения объекта класса [...].Такое исключение операций копирования / перемещения, называемое разрешением копирования, допускается в следующих случаях [...]:

  • в операторе возврата в функции с типом возврата класса, когда выражение являетсяимя энергонезависимого автоматического объекта [...] с тем же типом cv-unqualified, что и тип возвращаемого функцией, операция копирования / перемещения может быть опущена путем создания автоматического объекта непосредственно в возвращаемое значение функции
  • [...]

А теперь мне интересно, позволяет ли это в следующем коде ускользнуть от копирования

vector<string> gen(const char *fn) {
    if(fn == nullptr)  // this should prevent RVO
        return {"House", "Horse", "Hen"};
    vector<string> res;
    fillFromFile(res, fn);
    return res;  // copy elision possible?
}
int main() {
    vector<string> data = gen("users.dat");
}

ИлиРазве это правило не для примера, и я должен сделать это явно?

    return move(res);  // explicitly prevent copy

Обратите внимание, что мое намерение if состояло в том, чтобы устранить очевидное Возвращаемое значениеОптимизация (RVO).

Или я совершенно не на том пути?Произошло изменение, включающее return и move , которые могли бы использовать rvalue ссылок , верно?

Ответы [ 2 ]

3 голосов
/ 24 апреля 2011

Да, удаление копии возможно / разрешено в обоих случаях.

В терминологии компилятора эти два случая немного отличаются. return {"House", "Horse", "Hen"}; создает неназванный объект, поэтому включается обычный RVO.

return res; немного сложнее, потому что вы возвращаете именованный объект, который уже был построен ранее. Эта оптимизация обычно называется NRVO (оптимизация именованных возвращаемых значений), и ее компиляторы немного реже реализуют ее.

MSVC всегда реализует RVO и выполняет NRVO в выпусках сборки.

Я считаю, что последние версии GCC всегда выполняют как RVO, так и NRVO.

Кстати, я не очень понимаю, почему ваш «if» будет иметь значение для RVO.

0 голосов
/ 24 апреля 2011

Да, компилятор имеет специальные инструкции для обработки res как значения r в этом контексте, и res будет перемещено в data.Конечно, компилятор мог бы легко применить RVO / NRVO здесь в любом случае, потому что он может статически определять, что вы никогда не вызываете функцию с nullptr, и, кроме того, функция может быть тривиально преобразована, так что RVO / NRVO может применяться, даже еслине может быть доказано, и, наконец, это даже не мешает RVO / NRVO, так как результат все еще может быть получен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...