Чем C char отличается от строкового элемента C++, доступ к которому осуществляется с помощью индекса

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

   string str = "A man, a plan, a canal: Panama";
   str.erase(remove(str.begin(), str.end(), str[1]), str.end());

Результат: Аман, план, канал: Панаа

и если я использую, как показано ниже, результат будет таким, как ожидалось.

   string str = "A man, a plan, a canal: Panama";
   str.erase(remove(str.begin(), str.end(), ' '), str.end());

Результат: Аман, аплан, аканал: Панама

3 метода стилизации элементов HTML
3 метода стилизации элементов HTML
Когда дело доходит до применения какого-либо стиля к нашему HTML, существует три подхода: встроенный, внутренний и внешний. Предпочтительным обычно...
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
0
0
47
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Посмотрите на подпись std::remove:

template< class ForwardIt, class T >
ForwardIt remove( ForwardIt first, ForwardIt last, const T& value );

value передается по константной ссылке, поэтому после удаления первого пробела ваш str[1] указывает на неправильную память. Небезопасно получать доступ к элементам контейнера во время изменения контейнера.

И решение состоит в том, чтобы заранее передать static_cast<char>(str[1]) или присвоить str[1] переменной типа char.

Thomas 10.04.2022 12:20

@ Томас Хорошая идея; Я предпочитаю второй подход. Я вижу, что у Влада тоже есть аккуратная (хотя и немного непонятная) альтернатива.

Paul Sanders 10.04.2022 12:40

Алгоритм std::remove объявляется следующим образом

template<class ForwardIterator, class T>
ForwardIterator remove(
    ForwardIterator first, ForwardIterator last,
    const T& value // <-- reference!
);

Как видите, третий параметр объявлен как ссылка const T& value.

Итак, в этом вызове

str.erase(remove(str.begin(), str.end(), str[1]), str.end());

третий аргумент — ссылка на объект str[1], значение которого меняется в алгоритме на букву 'm' при встрече с первым символом ' '.

Если бы вы написали, например

str.erase(remove(str.begin(), str.end(), str[1] + 0), str.end());

вы получите ожидаемый результат, потому что в этом случае ссылка относится к временному объекту.

Другие вопросы по теме