11

以下是否根据 C++ 标准定义良好?

char* p = 0;
std::equal(p, p, p);

问题真的是这样的:

标准是否要求std::equal(begin1, end1, begin2)以这样的方式实现 if begin1 == end1, thenbegin1begin2可以是任何指针,甚至是不指向有效内存对象的指针?

我认为这是标准的意图,但我无法找到明确的声明。

我担心这一点的原因是,VisualStudio 显然试图检查begin2even when的“有效性” begin1 == end1。这与我对标准要求的理解相矛盾。

编辑:这是我认为违反标准的 VS 2012 的代码:

template<class _InIt1, class _InIt2> inline
bool equal(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2)
{   // compare [_First1, _Last1) to [First2, ...)
    _DEBUG_RANGE(_First1, _Last1);
    _DEBUG_POINTER(_First2);
    return (_Equal1(_Unchecked(_First1), _Unchecked(_Last1), _First2, _Is_checked(_First2)));
}

template<class _Ty> inline
void _Debug_pointer(const _Ty *_First, _Dbfile_t _File, _Dbline_t _Line)
{   // test iterator for non-singularity, const pointers
    if (_First == 0)
        _DEBUG_ERROR2("invalid null pointer", _File, _Line);
}
4

4 回答 4

9

所以我们有 25.2.1/1 它说:

返回: 如果对于 [first1,last1) 范围内的每个迭代器 i 都满足以下相应条件,则返回 true:*i == *(first2 + (i - first1)), pred(*i, *(first2 + (i - first1) ))) != 错误。

否则,返回 false。

在您的情况下,[0, 0) 范围内没有迭代器,因此该范围内的“每个”迭代器都通过了测试,但不应进行实际测试(因为要测试的范围内不存在迭代器)。

对我来说,它看起来像一个 VisualStudio 错误。

于 2013-10-01T16:06:18.490 回答
2

正如@Zac 指出的那样,此检查是 Visual Studio 以安全的名义更加迂腐。如果您希望 Visual Studio 即使在调试版本中也更符合标准,您可以通过将宏_ITERATOR_DEBUG_LEVEL 设置为 0 来关闭此行为。

于 2013-10-01T21:24:55.353 回答
0

随着你的更新,很明显这不是违反标准,而是调试检查。如果您在发布模式下编译它,这些检查不会运行,并且该函数与标准的描述相匹配。

在调试模式下获取该信息很有用,因为它将帮助您追踪一些难以发现的错误。

于 2013-10-01T18:18:57.050 回答
0

C++11 标准在 24.2.1/5 中声明“[i,i) 是一个空范围”。

但是,在 24.2.1/5 中,它首先暗示 0 必须是奇异值,然后声明“大多数表达式的结果对于奇异值是未定义的”。然后列出未定义行为的例外情况,但不包括比较。

因此,比较奇异迭代器的相等性可能是未定义的,因此使 [i, i) 无法评估。

运行时错误发生在名为 _Equal1() 的函数中也表明了这一点。

我认为标准对此含糊不清,我完全不确定这是 Visual Studio 2012 中的错误。

http://cplusplus.github.io/LWG/lwg-unresolved.html在“1213。有效和奇异迭代器未指定的含义”一章中,这种混淆也很有趣......

于 2013-10-02T13:01:58.163 回答