2017-05-29 5 views
0
#include <iostream> 
#include <vector> 

using namespace std; 

int main(){ 

    vector<int> VectorName; 

    VectorName.push_back(2); 
    VectorName.push_back(3); 

    cout << VectorName[1] << endl; 

    VectorName.pop_back(); 

    cout << VectorName[1] << endl; 

} 

私の理解では、pop_back ;ただし、コンソール上の出力は次のように述べました:pop_back関数を使ったクラステンプレートベクトルが意図したとおりに動作しない

このプログラムのコンパイルが成功した理由を誰かが説明しますか?

ありがとうございます。

+3

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

+2

未定義の動作です。 C++は実行時にエラーメッセージを表示することはほとんどありません。このエラーは一般にコンパイル時には診断できません –

+4

*このプログラムのコンパイルが成功した理由を説明しますか?* - プログラムを正常にコンパイルすると、正しい。プログラムが正しく実行されるかどうかは関係ありません。 – PaulMcKenzie

答えて

4

vector<>::operator[]()は、ベクトルのサイズをチェックしないため、コードで未定義の動作が生成されています。あなたの特定のケースで

あなたがpop_back()を呼び出すときに、ベクターは、容量(基本となる配列のサイズ)サイズ(ベクトル内の項目数)に縮小したが、されていません。これは、2番目のVectorName[1]が未使用だが既存のメモリを指していることを意味します。

#include <iostream> 
#include <vector> 

using namespace std; 

int main(){ 

    vector<int> VectorName; 

    VectorName.push_back(2); // |[2]| 
    VectorName.push_back(3); // |[2, 3]| 

    VectorName.pop_back(); // |[2], 3| 

    cout << VectorName.size() << endl; 
    cout << VectorName.capacity() << endl; 

} 

出力は次のとおりです:私たちは、容量やサイズを確認するために少しあなたの例を編集している場合たとえば、

あなたは見ることができますここでの実例:http://coliru.stacked-crooked.com/a/70d5141bdc375b48

ご覧のとおり、siベクトルのzeが正しい(1項目)が、VectorName.pop_back()を呼び出すと容量が減少しないので、ベクトルにはまだ3が存在しますが、アクセシブルではありません。

VectorName.pop_back()を呼び出した後に2番目の項目にアクセスすると、未定義の動作が発生しています。あなたの場合、3が得られますが、異なるコンパイラ、アーキテクチャ、またはマシンを使用してアプリケーションをコンパイルすると、アプリケーションがクラッシュする(または悪化する)可能性があります。

の代わりにvector<int>::at()を使用すると、プログラムがクラッシュするという例外が発生してstd::out_of_range例外がスローされます。これは、at()関数がベクトルのサイズをチェックし、ベクトルの範囲外の位置にアクセスしようとすると例外をスローするためです。つまり、at()関数に依存してベクトルアクセスをチェックするのではなく、VectorName[1]を呼び出す前にベクトルのsize()をチェックすることをお勧めします。

たとえば、再び自分のコードにマイナーな編集を行うことによって、我々は我々がat()機能使用時に何が起こるかを見ることができます:のインスタンスを投げた後に呼び出さ

#include <iostream> 
#include <vector> 

using namespace std; 

int main(){ 

    vector<int> VectorName; 

    VectorName.push_back(2); 
    VectorName.push_back(3); 

    cout << VectorName.at(1) << endl; 
    VectorName.pop_back(); 

    cout << VectorName.at(1) << endl; 

    return 0; 
} 

終了は、 'STD :: out_of_range'

もの():ベクトル:: _ M_range_check:(1)(1)__n> = this->サイズ()

bashの:行7:http://coliru.stacked-crooked.com/a/8226be85196f54fe


"コンパイルエラー" 上の1つの余分なもの:4793中止(コアダンプ)は

ライブ例./a.out。コンパイラは、アクセスする前にベクトルのサイズをチェックしようとしません。そのため、コンパイラはエラーや警告なしにコードをコンパイルします。開発者としては、コードの境界チェックを実行するのはあなた次第です。

+0

答えをありがとう、それは私に大きな洞察力を与えました。 – asd

関連する問題