16

ベクトルに適用された場合、C++ の clear 関数の動作を理解するのにいくつかの困難があります。

次の関数をコンパイルして実行しようとしました。

#include <iostream>
#include <vector>
using namespace std;

int main ()
{
  unsigned int i;
  vector<int> myvector;
  myvector.push_back (1);
  myvector.push_back (2);
  myvector.push_back (3);

  cout << "myvector contains:";
  for (i=0; i<myvector.size(); i++) cout << " " << myvector[i];

  myvector.clear();
  myvector.push_back (11);
  myvector.push_back (12);

  cout << "\nmyvector contains:";
  for (i=0; i<myvector.size(); i++) cout << " " << myvector[i];
  cout << endl;

  cout << " entry3 = " << myvector[2]<<endl;

  return 0;
}

そして、これは出力です:

myvector contains: 1 2 3
myvector contains: 11 12
entry3 = 3

ベクターをクリアするときに、ベクターの 3 番目のエントリの情報が消去されていない可能性があるのはなぜですか?

4

2 に答える 2

24

ドキュメントから:

ベクターのすべての要素が削除されます。それらのデストラクタが呼び出され、ベクター コンテナーから削除され、コンテナーのサイズは 0 のままになります。

基本的に、そのアイテムが存在しなくなったため、未定義の動作を呼び出しています。myvector[2]を呼び出した後、ベクトルに 2 つの要素をプッシュしただけなclear()ので、インデックス0とのみ1にアクセスできます。

動作しているように見えてもバグが隠れている可能性があるため、クラッシュしなかったのは運が悪いです。値が消去されるという保証はありません。

代わりにで要素にアクセスしようとすると.at(2)、例外がスローされます (operator[]()境界チェックは行われませんが、行われますat())。

于 2012-10-11T13:33:00.797 に答える
7

debugこのコードをモードで実行しようとすると、デバッグ アサーションでクラッシュする可能性があります。配列の末尾を超えて参照することは未定義の動作です。

実際に起こっていることは、 vector が実行前に使用していたメモリを消去していないことですclear()。このメモリはまだ存在しますが、アクセスするとどうなるかは定義されていません。ベクトルの端からはみ出さないように境界チェックを実行するのはあなた次第です。size()これを行うには、境界としてループするかat()、例外を使用してキャッチしout_of_rangeます。実行時チェックに例外を使用することはお勧めできないため、この後者のアプローチは特にお勧めしません。

于 2012-10-11T13:34:19.363 に答える