简体   繁体   English

如何检查迭代器指定的范围是否有效?

[英]How to check if a range specified by iterators is valid?

Many of the standard library containers have operations that accept a range specified by iterators.许多标准库容器具有接受迭代器指定范围的操作。 For example, std::list::assign(InputIterator first, InputIterator last) .例如, std::list::assign(InputIterator first, InputIterator last)

But because many of these operations do not throw exceptions, if the range specified by [first,last) is not valid, it will cause undefined behaviour.但是因为很多这些操作都不会抛出异常,如果[first,last)指定的范围无效,就会导致未定义的行为。

So what is a valid range?那么什么有效范围? I assume it means that first comes before or is equal to last in the container, because when I tried otherwise (ie first comes after last ), the program's execution would hang.我认为这意味着容器中first出现在或等于last之前,因为当我尝试其他方式时(即first出现在last之后),程序的执行将挂起。

For example:例如:

std::list.assign(container.begin(), container.end()); // valid range
std::list.assign(container.end(), container.begin()); // invalid range

Now with an assumption of what a valid range is, how can we check if a range is valid?现在假设有效范围是什么,我们如何检查范围是否有效?

I came up with a helper function that checks if first is ever equal to last before it reaches the end of the container.我想出了一个辅助函数,它在到达容器末尾之前检查first是否等于last If true, it's a strong guarantee that first does not come after last and therefore the range is valid.如果为真,则有力保证first不会在last之后出现,因此范围是有效的。

template <typename Iterator>
bool isValidRange(Iterator first, Iterator last, Iterator end)
{
  for (; first != end; ++first)
    if (first == last) return true;
  return false;
}

It's not very convenient because you have to pass it an iterator to the end of the container in addition to the iterators that specify the range.这不是很方便,因为除了指定范围的迭代器之外,您还必须将迭代器传递给容器的末尾。

Is this correct?这个对吗? Is there a better way to do this?有一个更好的方法吗?

how can we check if a range is valid? 我们如何检查范围是否有效?

You can't. 你不能。 Your function cannot guarantee that the range is valid, only that the last is reachable from the first. 您的函数不能保证范围有效,只能从最后一个可以到达。 These are two different things (for a simple example, consider an iterator into a vector which was subsequently reallocated). 这是两个不同的事情(对于一个简单的例子,考虑将迭代器转换为随后重新分配的向量)。 There is no mechanism by Standard that permits you to check if a range is valid. 标准没有允许您检查范围是否有效的机制。 Much like you cannot know that a pointer is valid before you de-reference it. 就像你在取消引用之前无法知道指针有效一样。

Just to note, Microsoft provided a function to check if a pointer was valid and it utterly screwed everyone who used it. 需要注意的是,Microsoft提供了一个函数来检查指针是否有效,并且完全搞砸了使用它的每个人。 Raymond Chen said that it should have been named CorruptMemoryIfPossible. 雷蒙德陈说它应该被命名为CorruptMemoryIfPossible。

[iterator.requirements.general] defines the "valid range" term: [iterator.requirements.general]定义了“有效范围”术语:

10 A sentinel s is called reachable from an iterator i if and only if there is a finite sequence of applications of the expression ++i that makes i == s. 10 当且仅当存在使 i == s 的表达式 ++i 的有限应用序列时,才称哨兵 s 从迭代器 i 可达。 If s is reachable from i, [i, s) denotes a valid range.如果 s 可以从 i 到达,则 [i, s) 表示有效范围。

So "last is reachable from the first" is exactly equal to "valid range" definition from the standard PoV (and hence for UB definition).因此,“从第一个开始就可以到达最后一个”完全等于标准 PoV 中的“有效范围”定义(因此对于 UB 定义)。 Dereferencability of iterators is orthogonal to this definition.迭代器的可解引用性与此定义正交。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM