Как обойти C ++ std :: string_view вне области видимости? - PullRequest
0 голосов
/ 06 марта 2020

В следующей статье в разделе «Вопросы прав собственности» упоминается, что если кто-то настраивает std :: string_view для просмотра переменной std :: string, то оставляет область действия этого std :: string, std: : поведение string_view будет неопределенным.

https://www.learncpp.com/cpp-tutorial/6-6a-an-introduction-to-stdstring_view/

Я понимаю, что это связано с тем, что переменная std :: string больше не находится в области видимости и "умирает", так что то, что просматривается std :: string_view, не определено. Как можно обойти это?

Моя текущая функция что-то делает для этого:

std::string_view mergeIntoSV(std::string str1, std::string str2) {
  std::string new_str = str1 + str2;
  return std::string_view { new_str };
}

void callMerge() {
  std::string list[10];
  std::string_view views[5];
  //Assume some code that populates "list"...
  for (int i = 0; i < 10; i+=2) {
    views[i/2] = mergeIntoSV(list[i], list[i+1]);
  }
  //Now I want to be able to read each of the std::string_views.
}

Однако после вызова этой функции в другом месте и последующего чтения содержимого возвращенного std :: string_view, Я (как предполагает статья) прочитал некоторое неопределенное строковое значение. К сожалению, я не могу просто изменить тип возвращаемого значения на std :: string из-за того, что я работаю с большей кодовой базой и требует, чтобы возвращаемый тип был таким, как есть.

Как обойти это проблема?

Ответы [ 2 ]

8 голосов
/ 06 марта 2020

Вы создаете строковый объект в концептуально чистой функции (нет состояния вне входов / выходов). Затем вы решили, что эта чистая функция должна возвращать несобственное представление этого объекта. Это противоречие: чистая функция не может владеть состоянием после того, как функция завершила выполнение. И если функция не владеет этим состоянием, а возвращаемое значение не владеет этим состоянием ... состояние не существует.

У вас есть только два варианта: вернуть что-то, что на самом деле владеет строкой или сделать функцию не чистой, создав ей строку, которая переживает вызов функции (это может быть через stati c local, global или любое количество вещей). Последнее почти всегда является неправильным ответом.

Если для этой операции требовалась какая-то более крупная кодовая база, то у этой более крупной кодовой базы есть проблема проектирования, которую необходимо решить.

1 голос
/ 06 марта 2020

Представление строки не волшебно: по сути, это просто указатель на начало строки и ее длину. Точно так же, как вы не вернете указатель на локальную переменную, вы не вернете std::string_view к локальной строке. Это так просто.

«Решение» такое же, как и для указателей:

  • Если объект (строка) должен быть локальным - не возвращать указатель (представление строки) к нему.
  • Если время жизни (строки) объекта должно увеличивать время жизни, либо:
    • возврат по значению (есть гарантированное разрешение на возврат возвращаемого значения и NRVO ) или
    • создайте буфер, скажем, через std::unique_ptr, а затем переместите-верните его, или
    • передайте буфер для работы в качестве ввода и используйте его для строковых данных .
...