デバッグの反復子のサポート
Visual C++ ランタイム ライブラリは実行時に不適切な反復子の使用を検出し、ダイアログ ボックスを表示して、を表示します。デバッグの反復子のサポートを有効にするには、プログラムをコンパイルに.の C ランタイム ライブラリのデバッグ バージョンを使用する必要があります。詳細については、「CRT ライブラリの機能」を参照してください。反復子を使用する方法の詳細については、チェックを行う反復子を参照してください。
C++ 標準では、メンバー関数により、コンテナーに反復子が無効になる可能性があるかについて説明します。2 例は次のとおりです:
コンテナー オフにより反復子は、から要素を要素に無効になります。
ベクター のサイズを大きくすると、vector にプッシュまたは (挿入) 反復子は無効になります。
使用例
デバッグ モードで次のプログラムをコンパイルして実行時に保持して終了します。
/* compile with /EHsc /MDd */
#include <vector>
#include <iostream>
int main() {
std::vector<int> v ;
v.push_back(10);
v.push_back(15);
v.push_back(20);
std::vector<int>::iterator i = v.begin();
++i;
std::vector<int>::iterator j = v.end();
--j;
std::cout<<*j<<'\n';
v.insert(i,25);
std::cout<<*j<<'\n'; // Using an old iterator after an insert
}
デバッグ ビルドの反復子のデバッグ機能を無効に _HAS_ITERATOR_DEBUGGING シンボルを使用できます。次のプログラムはアサートされませんが、未定義の動作が発生します。
重要 |
---|
_HAS_ITERATOR_DEBUGGINGを制御するために _ITERATOR_DEBUG_LEVEL を使用します。詳細については、「_ITERATOR_DEBUG_LEVEL」を参照してください。 |
// iterator_debugging.cpp
// compile with: /EHsc /MDd
#define _HAS_ITERATOR_DEBUGGING 0
#include <vector>
#include <iostream>
int main() {
std::vector<int> v ;
v.push_back(10);
v.push_back(15);
v.push_back(20);
std::vector<int>::iterator i = v.begin();
++i;
std::vector<int>::iterator j = v.end();
--j;
std::cout<<*j<<'\n';
v.insert(i,25);
std::cout<<*j<<'\n'; // Using an old iterator after an insert
}
アサートは、初期化前に次に示すように、反復子を使用しようとした場合に発生します:
/* compile with /EHsc /MDd */
#include <string>
using namespace std;
int main() {
string::iterator i1, i2;
if (i1 == i2)
;
}
for_each のアルゴリズムの 2 反復子が互換性がないため、次のコード例に、アサーションが発生します。アルゴリズムは、に指定されている反復子が同じコンテナーを参照しているかどうかを確認します。
/* compile with /EHsc /MDd */
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
vector<int> v1;
vector<int> v2;
v1.push_back(10);
v1.push_back(20);
v2.push_back(10);
v2.push_back(20);
// The next line will assert because v1 and v2 are
// incompatible.
for_each(v1.begin(), v2.end(), [] (int& elem) { elem *= 2; } );
}
この例では、ファンクタの代わりにラムダ式 [] (int& elem) { elem *= 2; } を使用することに注意してください。このオプションは関係ありませんが、ASSERT エラーの同様のラムダ ファンクタにより、同じエラーは、小さな関数オブジェクトのタスクを実行する非常に便利な手段発生します。ラムダ式の詳細については、「C++ でのラムダ式」を参照してください。
また、このチェックするデバッグの反復子により for のループのスコープが終了すると for のループでスコープ外になるように宣言された反復子変数が発生します。
// debug_iterator.cpp
// compile with: /EHsc /MDd
#include <vector>
#include <iostream>
int main() {
std::vector<int> v ;
v.push_back(10);
v.push_back(15);
v.push_back(20);
for (std::vector<int>::iterator i = v.begin() ; i != v.end(); ++i)
;
--i; // C2065
}
デバッグの反復子に重要なデストラクターが存在する。デストラクターが、いかなる理由であれ実行されていない場合、アクセス違反およびデータ破損が発生する場合があります。次の例について考えます。
/* compile with: /EHsc /MDd */
#include <vector>
struct base {
// FIX: uncomment the next line
// virtual ~base() {}
};
struct derived : base {
std::vector<int>::iterator m_iter;
derived( std::vector<int>::iterator iter ) : m_iter( iter ) {}
~derived() {}
};
int main() {
std::vector<int> vect( 10 );
base * pb = new derived( vect.begin() );
delete pb; // doesn't call ~derived()
// access violation
}