2016-07-21 9 views
1

Hereのコード:なぜデータベクタをクリアした後でもそれにアクセスできますか?

vector<double> samples; 

int main() 
{ 
    samples.resize(100); 
    for(int i=0; i<100; i++) { 
     samples[i]=i/100.0; 
    } 

    samples.clear(); 
    cout << "vector size: " << samples.size() << endl; 
    cout << "... but samples[9]=" << samples[9] << endl; 
} 

て出力する:

vector size: 0 
... but samples[9]=0.09 

ベクトルをクリアした後、私はまだそのデータにアクセスすることができます(サイズは0です)。それは普通ですか?

Referenceによると、要素は「破棄されます」と表示されますが、「デフォルト/空」の値ではないようです。私は、実行時に「範囲外」のエラーメッセージになるだろう他の言語では

...それは、「デフォルト/空」の値を意味するものではありませんようだ

+1

'samples.at(9)'を使ってみましたか? –

+1

未定義の動作は未定義です。 –

+1

サイズはゼロに設定されていますが、容量は変更されていません。割り当てられたストレージはまだそこにあり、再利用を待っています。 – user4581301

答えて

5

はい、それはちょうどUBです。

std::vector::operator[]は境界チェックを実行しませんが、std::vector::at()は例外であり、ケースの場合はstd::out_of_rangeの例外がスローされます。

+0

clear()は、内部サイズ値を0に設定するだけです。ベクトルクラスは実際のサイズよりも多くのメモリを予約しているため、再割り当てなしでpush_back()を使用できるようにするため、clear()が予約される前にベクターで以前に使用されていたメモリが予約されています:そのため演算子[]は例外をスローしません。しかし、songyuanyaoが言及しているように、at()を使用すると、引数 – wasthishelpful

+0

@を確認することができます。これが、「演算子[]が例外をスローしない理由です」。これは誤解を招くかもしれません。 'std :: vector :: operator []'は例外をスローしません。 – songyuanyao

+0

あなたは正しいです^^私はこの特定の点だけを話していました – wasthishelpful

2

C++はJava、C#またはPythonのような多くのものが、エラーを生成する代わりに未定義の動作として定義されている点で異なります。アレイのアウトオブバウンドアクセスをチェックすることはそのような例です。定義されていない動作のため、this also gives the compiler a great degree of freedom to optimize your code

具体的なケースでは、std::vector::operator[]経由でアクセスが制限されていることは、未定義の動作です。コンパイラは自由に任意の動作を生成できます。一般的なケースは、メモリ位置へのアクセスを実行し、そこにあるものを返すことです。

関連する問題