c – `std :: string :: begin()`/`std :: string :: end()`的迭代器失效?

前端之家收集整理的这篇文章主要介绍了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仍然有资格作为一个有效的迭代器,因此没有被无效?
>上面的代码是否在C 98中定义得很好?在C 11中,禁止写入时复制实现?

根据我自己对规范的简要介绍,它看起来不明确,因此可能无法保证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()或[]才能使迭代器无效.

猜你在找的C&C++相关文章