我正在使用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());
结果 : 阿曼,阿普兰,阿卡纳尔:巴拿马
看看std::remove
的签名:
template< class ForwardIt, class T >
ForwardIt remove( ForwardIt first, ForwardIt last, const T& value );
value
是通过 const 引用传递的,因此在删除第一个空格后,您的str[1]
指向错误的内存。在修改容器时访问容器元素是不安全的。
算法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());
您将获得预期的结果,因为在这种情况下,引用引用临时对象。