11

以下は、C++ 標準に従って適切に定義されていますか?

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

質問は本当にこれです:

標準では、 if 、 then 、およびが有効なメモリ オブジェクトを指していない場合でも、任意のポインターになるようstd::equal(begin1, end1, begin2)に実装されている必要がありますか?begin1 == end1begin1begin2

これが標準の意図だと思いますが、これを明確にするステートメントを見つけることができませんでした。

私がこれについて心配している理由は、VisualStudio がbegin2いつでも「有効性」をチェックしようとするように見えるから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 に答える
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 に答える