3

「アサート」とは正確には何ですか。より具体的には、エラーを取り除くにはどうすればよいですか。データ メンバー int x を持つクラスへのポインターのベクトルを作成し、次のようにします。

for(I=antiviral_data.begin();I<antiviral_data.end();I++)
{
    if((*I)->x>maxx)
    {
        antiviral_data.erase(I);
    }
}

プログラムを実行すると、x が maxx よりも大きくなるまでエラーは発生せず、.erase() を使用すると、次のエラーが発生します。

デバッグ アサーションに失敗しました!

プログラム: ...My Documents\O.exe ファイル: ...include\vector 行: 116

式: ("this->_Has_container()",0)

プログラムがどのようにアサーション エラーを引き起こすかについては、アサートに関する Visual C++ のドキュメントを参照してください。

(アプリケーションをデバッグするには、[再試行] を押します)

[中止][再試行][無視]

また、cout を使用しようとすると、次のようになります。

cout<<(*antiviral_data.begin())->x<<endl;

次のエラーが表示されます。

デバッグ アサーションに失敗しました!

プログラム: ...My Documents\O.exe ファイル: ...include\vector 行: 98

式: ベクトル反復子は deferencable ではありません

プログラムがどのようにアサーション エラーを引き起こすかについては、アサートに関する Visual C++ のドキュメントを参照してください。

(アプリケーションをデバッグするには、[再試行] を押します)

[中止][再試行][無視]

ベクター内のデータを使用できない理由と、それを修正する方法を教えてください。

また、 antiviral_data は、単一の要素を持つポインターのベクトルです。

antiviral_data.push_back(new aX1(player.x,player.y,'>'));

それが役立つ場合。

4

4 に答える 4

11

アサーションを取得する最も可能性の高い理由は、消去後に I をインクリメントすることです。代わりにこれを試してください:

for(I=antiviral_data.begin();I!=antiviral_data.end();)
{
    if((*I)->x>maxx) I=antiviral_data.erase(I); else ++I;
}

http://www.cppreference.com/wiki/stl/vector/eraseも参照してください。そのページで無効なイテレータを検索してください。

于 2009-05-03T16:33:02.143 に答える
7

assert は通常、デバッグとエラー制御の目的で開発者が入力する式です。コードにさまざまな「健全性チェック」を入れ、チェックに達しない場合はプログラムをクラッシュさせます。

たとえば、どこかで 2 つの数値を除算するコードがあるとします。ゼロ以外による除算を常に期待していますが、引数が誤って計算された場合に備えて、除算の前に at assert を置きます。アサートが失敗した場合は、どこかで失敗したことを意味します。

通常、アサーションはコードのデバッグ バージョンにのみ表示されます (ビジュアル C++ を使用している場合は、デバッグおよびリリース用にコンパイルできます)。リリース モードでコンパイルすると結果はなくなりますが、それでもエラーが発生し、おそらく非常に悪い結果になるため、これは非常に悪い考えです。

Vector の実装のどこか (標準ですか)、特に 98 行目に assert があります。ベクターコードにアクセスできる場合は、アサートが何であるかを確認するか、その時点までデバッグしてください。これは、ベクターの実装またはベクターを呼び出すコードにエラーがあることを示している可能性があります。

あなたが投稿したものは、何が起こっているのかについてのヒントを私たちに与えてくれますが、ベクトルが定義されている場所を含め、プログラムをさらに貼り付けていただけると便利です.

于 2009-05-03T16:29:18.283 に答える
1

問題は消去呼び出しにあります。コンテナを繰り返し処理し、同時にコンテナから要素を消去しています。消去を行った後、イテレータは無効になります。ベクトルから特定の値の要素を削除する場合は、remove_if アルゴリズムを使用して消去します。これは消去削除イディオムとして知られており、Scott Meyer の効果的な STL の本で非常によく説明されています。詳細については、この質問Erasing elements from a vectorを参照することもできます。

于 2009-05-03T16:38:38.323 に答える
0

アサーションとは何か、そしてなぜそれがコードでトリガーされるのかについて、すでにいくつかの良い答えがあります。ここで、2パス消去にSTLアルゴリズムを使用することを検討することをお勧めします。

namespace {
   struct exceeds : public std::unary_function< TheUnknownType*, bool >
   {
      exceeds_max( int max ) : maxx( max ) {}
      bool operator()( TheUnknownType* data ) {
         return data->x < max;
      } 
   private:
      int maxx;
   };
}
void your_function()
{
   std::vector< TheUnknownType* >::iterator new_end;
   new_end = std::remove_if( antiviral_data.begin(), antiviral_data.end(), exceeds(maxx) );
   antiviral_data.remove( new_end, antiviral_data.end() );
}

主な利点は、ベクトル内の要素の消去はコストのかかる操作であるということです。消去される要素ごとに、その位置からベクトルの終わりまでのすべての要素を、最初に向かって1つの位置に移動する必要があります。消去する2番目の要素は、そこからすべての要素の2番目の移動を強制します... STL remove_ifアルゴリズムは、移動を1回だけ実行して最終位置に移動し、削除されていない要素の最後の要素を1つ超えたイテレータを返します。次に、要素を再配置する必要のない単一のstd :: vector <>::removeを実行できます。

于 2009-05-03T18:05:21.890 に答える