Посмотрите на этот пример (взято из здесь):

class foo {
    std::string my_str_;

public:
    std::string_view get_str() const {
        return my_str_.substr(1u);
    }
};

Этот код плох, потому что substr возвращает временный std::string, поэтому возвращенный std::string_view ссылается на уже уничтоженный объект. Но если substr вернул std::string_view, эта проблема не существовала бы.

Кроме того, мне кажется логичным, если substr вернул std::string_view вместо std::string, потому что возвращаемая строка является представлением строки и более производительна, потому что копия не создается.

Будут ли какие-либо недостатки, если substr вернул std::string_view (кроме очевидного недостатка: потеря некоторой совместимости с C ++ 14 - я не недооцениваю важность этого, я просто хотел бы знать, есть ли другие недостатки есть)?

Смежный вопрос: Как эффективно получить `string_view` для подстроки` std :: string`

6
geza 4 Сен 2017 в 13:47

4 ответа

Лучший ответ

Вот конкретный (если немного неполный) пример кода, который в настоящее время безопасен, но с изменением станет неопределенным поведением:

std::string some_fn();
auto my_substr = some_fn().substr(3, 4);

Возможно, использование auto здесь немного сомнительно, но вполне разумно (на мой взгляд) в следующей ситуации, когда повторение имени типа будет почти избыточным:

const char* some_fn();
auto my_substr = std::string(some_fn()).substr(3, 4);

Редактировать: Даже если substr() всегда вернул std::string_view, вы можете представить, что этот код вызывает некоторую боль, даже если только во время разработки / отладки.

2
Arthur Tacca 4 Сен 2017 в 12:05

Недостаток кристально ясен: это было бы существенным изменением API по сравнению с каждой версией C ++, начиная с самого начала.

C ++ не является языком, который нарушает совместимость API.

3
John Zwinck 4 Сен 2017 в 10:57

Когда string_view был изобретен, было слишком много споров о том, должно ли оно быть там. Все противоположные аргументы вытекали из примеров, подобных тому, который вы показали.

Однако, как я всегда говорю всем с такими плохими примерами: C ++ - это не Java и не Python. C ++ - это язык низкого уровня, где у вас почти полный контроль над памятью, и я повторяю клише из Spiderman: «С большой силой приходит большая ответственность. Если вы не знаете, что такое string_view, не используйте его!

Другая часть вашего вопроса имеет простой ответ, и вы ответили на него сами:

Будут ли какие-либо недостатки, если substr возвращает std :: string_view (кроме очевидного недостатка: потеря некоторой совместимости с C ++ 14)?

Вред в том, что каждая программа, которая использовала копию строки из substr, может быть недействительной. Обратная совместимость - серьезная вещь в компьютерном бизнесе, поэтому 64-разрядные процессоры Intel по-прежнему принимают инструкции по x86, и поэтому они не выходят из бизнеса. Изобретать колесо стоит больших денег, и деньги играют важную роль в программировании. Так что, если вы не планируете выбросить весь C ++ в мусор и начать все сначала (как это сделал RUST ), вы должны поддерживать старые правила в каждой новой версии.

Вы можете осудить вещи, но очень осторожно и очень медленно. Но не рекомендуется менять API, как вы и предлагаете.

4
The Quantum Physicist 4 Сен 2017 в 11:14

С одной стороны, базовая структура данных строки c ++ по большей части совместима со строкой c (доступна через член c_str()). Строки C завершаются null. Таким образом, у вас просто есть начальный указатель char, и продолжайте увеличивать его, пока указатель не укажет на 0.

Таким образом, подстрока может начинаться с произвольной позиции вашей исходной строки. Однако, поскольку вы не можете просто вставить null где-нибудь в исходной строке, ваша подстрока все равно должна заканчиваться в той же позиции, что и оригинал.

--редактировать-- как отметил Джон Цвинк, строки c ++ могут содержать символы \0, однако это все равно будет означать, что подстроки потеряют свой член c_str, так как для этого потребуется изменить исходную строку. Недостаток string_view, который также был замечен в Использование std :: string_view с api, что ожидает завершенную нулем строку

1
Lanting 4 Сен 2017 в 11:50