Оптимизация компилятора с возвратом (std::stringstream ss).str()

Следующая функция принимает строку в качестве аргумента и возвращает другую после некоторой обработки.

  1. Достаточно ли справедливо предположить, что компилятор выполнит оптимизацию перемещения, и я не буду копировать содержимое строки после каждого вызова? Должна ли эта функция следовать copy elision [(N)RVO]?

  2. Целесообразно ли это на практике?

std::string foo(std::string const& s)
{ // Perform sanity check on s
  // ...

  std::stringstream ss;
  // do something and store in ss
  // ...

  return ss.str();
}

Потому что в противном случае я обычно следую практике возврата строк по ссылке. Итак, сигнатура моей функции была бы такой:

void foo (std::string const& inValue, std::string& outValue);

person hell_ical_vortex    schedule 02.02.2016    source источник
comment
вам не о чем беспокоиться, компилятор оптимизирует копирование путем перемещения или исключения.   -  person David Haim    schedule 02.02.2016
comment
Если вы поместите s в этот stringstream, то я почти уверен, что он будет скопирован при входе и скопирован при выходе.   -  person Galik    schedule 02.02.2016
comment
Вы можете написать return std::move(ss).str() на тот случай, если ваша реализация оптимизирует этот случай (еще не уверен, что это возможно).   -  person Marc Glisse    schedule 02.02.2016
comment
Я могу понять обратный ход(); часть! Но я не могу понять последнюю часть вашего комментария «не уверен, что кто-то еще»   -  person hell_ical_vortex    schedule 03.02.2016


Ответы (2)


ss.str() создаст временную строку. Если вы назначаете эту строку новому экземпляру, например

std::string bar = foo("something");

Сработает семантика копирования или перемещения.

Теперь, если у вас есть уже созданная строка, и вы назначаете ее для возврата foo, тогда сработает назначение перемещения.

std::string bar;
// do stuff
bar  = foo("something");

Я предпочитаю этот метод, так как он не требует, чтобы у вас уже был создан объект, где

void foo (std::string const& inValue, std::string& outValue);

Вы бы создали пустую строку, чтобы передать ее функции для заполнения. Это означает, что у вас есть конструкция и задание, тогда как в первом примере вы могли бы просто иметь конструкцию.

person NathanOliver    schedule 02.02.2016
comment
Я упустил детали «сайта вызова»! Спасибо за подробную иллюстрацию. - person hell_ical_vortex; 02.02.2016
comment
@bvraghav Нет проблем. Рад помочь. - person NathanOliver; 02.02.2016

Согласно это более оптимизировано, когда вы возвращаете значение:

Оптимизация возвращаемого значения (RVO) позволяет компилятору оптимизировать копию, заставляя вызывающую и вызываемую сторону использовать один и тот же участок памяти для обеих «копий».

person RealityTS    schedule 02.02.2016