c – `std :: string :: begin()`/`std :: string :: end()`的迭
#include <string> #include <iostream> int main() { std::string s = "abcdef"; std::string s2 = s; auto begin = const_cast<std::string const &>(s2).begin(); auto end = s2.end(); std::cout << end - begin << 'n'; } 此代码将begin()const的结果与end()的结果混合在一起.这些函数都不允许使任何迭代器无效.但是我很好奇是否要求end()不使iterator变量begin失效实际上意味着变量begin可以用于end. 考虑一下C8,std :: string的copy-on-write实现;非const begin()和end()函数会导致复制内部缓冲区,因为这些函数的结果可用于修改字符串.因此,上面的开始对s和s2都有效,但是使用非const end()成员会使它不再对s2(生成它的容器)有效. 上面的代码使用copy-on-write实现(例如libstdc)产生“意外”结果.而不是结束 – 开始与s2.size(),libstdc produces another number相同. >导致开始不再是s2的有效迭代器,从中检索它的容器,构成’使迭代器无效’吗?如果你看一下迭代器的要求,它们在调用.end()之后似乎都保留了这个迭代器,所以也许begin仍然有资格作为一个有效的迭代器,因此没有被无效? 根据我自己对规范的简要介绍,它看起来不明确,因此可能无法保证begin()和end()的结果可以一起使用,即使没有混合const和非const版本. 解决方法
如你所说,C 11在这方面与早期版本不同. C 11中没有问题,因为删除了所有允许写入时复制的尝试.在C 11之前,您的代码会导致未定义的行为;允许调用s2.end()使现有的迭代器无效(并且在g中完成,也可能仍然如此).
请注意,即使s2不是副本,标准也会允许它使迭代器无效.实际上,C 98的CD甚至可以使用f(s.begin(),s.end())或s [i] == s [j]这些未定义的行为.这只是在最后一刻才实现,并进行了更正,以便只有第一次调用begin(),end()或[]才能使迭代器无效. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |