为什么我需要转换算法remove()的参数?

时间:2017-06-15 18:58:44

标签: c++ pointers casting reference

我正在尝试从"helloworld"等字符串中删除连续的重复字符,并删除所有重复字符。在这种情况下,它是'l',因此新字符串应为"heoword"。我写了这样的代码:

#include <algorithm> 
#include <string>
#include <iostream>  

using namespace std; 

int main() { 
  string s = "helloworld"; 
  for (int i = 0; i < s.length() - 1; i++) { 
    if (s[i] == s[i+1]) { 
      s.erase(remove(s.begin(), s.end(), s[i]), s.end()); // PROBLEM
      cout << s << endl; // printing `heowrld`, instead of `heoword`
    } 
  }
  return 0;  
}

上述代码不起作用,除非我像s[i]一样投射(char)s[i]。我查找了操作符[]以获取字符串,并返回对位置字符的引用。 remove方法还接受const T& val作为要替换的字符的参数。由于它们都属于同一类型,为什么我只能将s[i]作为remove方法的参数?

P.S。这不是作业问题。通过在s[i]中投射remove,我可以获得正确的输出,但我想知道为什么我需要投射s[i]

1 个答案:

答案 0 :(得分:2)

这里的问题是你移动值从你自己身下移除。让我们看看

#include <iostream>

int main() 
{
    int a = 5, b = 10;
    int & ref = a;
    std::cout << "a: " << a << " b: " << b << " ref: " << ref << "\n";
    std::swap(a, b);
    std::cout << "a: " << a << " b: " << b << " ref: " << ref << "\n";
}

如果你运行它,你会得到

a: 5 b: 10 ref: 5
a: 10 b: 5 ref: 10

正如您所看到的那样ref现在不会移至b,而是停留在a(应该如此)并打印a的新值。

我们看到了同样的事情
s.erase(remove(s.begin(), s.end(), s[i]), s.end());

由于s[i]是对字符串中元素的引用,因此当删除交换元素时,其值会发生变化。因此它删除了l两个,然后删除了最后o,因为o被移动到l曾经占据的相同位置,但它只会在它传递了字符串中的第一个o

施放“修复”这个的原因是因为现在你不再引用字符串的元素了。您创建一个临时变量,并使用该变量值来删除l