Mal*_*ous 7 c++ iterator reference
我似乎无法找到关于迭代器是否保持它们迭代的底层对象的大量信息.
如果我创建一个迭代器,那么提供它的对象超出了范围,迭代器的存在是否会阻止它被破坏?
这是一个非常简单的例子,仅用于说明该场景:
// This class takes a copy of iterators to use them later
class Data {
public:
Data(std::vector<int>::iterator start, std::vector<int>::iterator end)
: start(start),
end(end)
{}
void show() {
// Use this->start and this->end for some purpose
}
private:
std::vector<int>::iterator start;
std::vector<int>::iterator end;
};
Data test() {
std::vector<int> v{1, 2, 3};
Data d(v.begin(), v.end());
d.show(); // this would be ok
return d;
}
int main(void) {
Data d = test();
d.show(); // What happens here?
}
Run Code Online (Sandbox Code Playgroud)
在此示例中,Data对象正在存储迭代器的副本,这对第一次show()调用很好.但是,到第二次show()调用时,提供迭代器的原始对象不再存在.
迭代器是否保留对象直到它们全部被破坏为止,或者一旦原始对象超出范围,迭代器就会失效?
这是许多人的一个参考,它没有说明一种方式或另一种方式发生了什么(或者甚至是否结果是'未定义'.)
迭代器通常不拥有它们迭代的数据,不.事实上,他们很少(如果有的话)甚至意识到拥有数据的对象; 例如,向量迭代器通常只是指针,它们不知道任何向量或其生命周期.即使那些没有实现为指针的迭代器(它们中的大多数)也可以被认为是一种"指针",并且被视为这样:它们很容易变得晃来晃去.
你的例子有UB,因为你将show()在第二次取消引用无效的迭代器.
如果容器超出范围,则所有迭代器都将失效.事实上,迭代器可能会失效的原因各不相同,例如在操作导致容量扩展时添加向量.
这有可能发现迭代器做的,而不是遍历其他地方(如发现了一些收集那种"自己"的数据,Boost的计数迭代器),但这些都是利用C++的优势,提供一个神奇的功能,而不是固有属性的魔法属性由C++定义的迭代器.