Является ли `string.assign (string.data (), 5)` хорошо определенным или UB? - PullRequest
11 голосов
/ 13 февраля 2020

Коллега хотел написать это:

std::string_view strip_whitespace(std::string_view sv);

std::string line = "hello  ";
line = strip_whitespace(line);

Я сказал, что возвращение string_view сделало меня неловким априори , и, кроме того, псевдоним здесь выглядел как UB для меня.

Могу с уверенностью сказать, что line = strip_whitespace(line) в этом случае эквивалентно line = std::string_view(line.data(), 5). Я полагаю, что это вызовет string::operator=(const T&) [with T=string_view], который определен, чтобы быть эквивалентным line.assign(const T&) [with T=string_view], который определен, чтобы быть эквивалентным line.assign(line.data(), 5), который определен для этого:

Preconditions: [s, s + n) is a valid range.
Effects: Replaces the string controlled by *this with a copy of the range [s, s + n).
Returns: *this.

Но это не говорит о том, что происходит, когда происходит псевдоним.

Вчера я задал этот вопрос на cpplang Slack и получил смешанные ответы. Ищите здесь супер-авторитетные ответы и / или эмпирический анализ реализаций реальных поставщиков библиотек.


Я написал тестовые примеры для string::assign, vector::assign, deque::assign , list::assign и forward_list::assign.

  • Libc ++ заставляет все эти тестовые случаи работать.
  • Libstdc ++ заставляет их все работать, кроме forward_list, что приводит к ошибкам.
  • Я не знаю о библиотеке MSV C.

Ошибка в libstdc ++ дает мне надежду, что это UB; но я также вижу, что и libc ++, и libstdc ++ будут прилагать большие усилия, чтобы сделать эту работу, по крайней мере, в обычных случаях.

1 Ответ

8 голосов
/ 13 февраля 2020

За исключением пары исключений, которые не являются вашими, вызов неконстантной функции-члена (например, assign) для строки делает недействительными [...] указатели [...] на его элементы. Это нарушает предварительное условие на assign, что [s, s + n) является допустимым диапазоном, поэтому это неопределенное поведение.

Обратите внимание, что string::operator=(string const&) имеет язык, специально предназначенный для самостоятельного назначения, а не -op.

...