我相信对此的常见反应是“不”,end()因为容器的迭代器表示“过去结束”地址,这是取消引用的未定义行为。我在标准中找不到一个明确的声明来免除字符串的约束,即使字符串比其他容器有特殊情况。
C++11 标准声明您可以读取超过字符串末尾的一个索引。string[size()]引用空终止符的只读值。
24.3.2.5 basic_string 元素访问 [string.access]
const_reference operator[](size_type pos) const;
reference operator[](size_type pos);(1)要求:
pos <= size().(2)回报:
*(begin() + pos) if pos < size()。否则,返回对类型charT为 value的对象的引用charT(),其中将对象修改为除charT()导致未定义行为之外的任何值。
front()被定义为等效于return operator[](0)which 等效return operator[](size())于一个空字符串。
end() - begin()被明确定义为字符串长度的差异,因此end()必须指向的索引size()才能定义该算术。
在上面的标准摘录中,它说明这operator[](pos)等效于*(begin() + pos)if pos < size()。它并不是说您可以取消引用begin() + size(),但您认为假设这应该被明确定义是否合理?或者更好的是,您是否知道一些证明可以将字符串迭代器从约束中排除?
另外,能否证明*(begin() + i)for …
如果你能为我清除一些困惑,我想要它.我正在编写一个函数来删除字符串中的重复字符,例如"AB - >"AAABB".
void remove_dups(std::string& str) {
std::string::iterator it = str.begin();
while (it != str.end()) {
if (*(it+1) == *it) {
str.erase(it+1);
} else {
++it;
}
}
}
Run Code Online (Sandbox Code Playgroud)
它在测试时似乎有效.但是,我想知道,不应该有栅栏问题吗?当'it'是字符串的结尾时,if语句会查看不存在的下一个字符.根据cplusplus.com,
过去的结尾字符是一个理论字符,它将跟随字符串中的最后一个字符.它不应被解除引用.( http://www.cplusplus.com/reference/string/string/end/)
所以我想知道为什么我的函数似乎通过了测试,以及如何以优雅的方式重写整个事情来绕过fencepost问题.(对我来说很容易,伙计.我是一个n00b.)
像它一样重写它
void remove_dups(std::string& str) {
std::string::iterator it = str.begin();
while (it != str.end()) {
if ((it+1) != str.end() && *(it+1) == *it) {
str.erase(it+1);
} else {
++it;
}
}
}
Run Code Online (Sandbox Code Playgroud)
似乎不优雅.