1

コードの一部を検討する

int main(int argc,char* argv[]){
        int *arrPtr = new int[4];
        for (int i=0;i<4;i++)
                arrPtr[i]=i*2;


        for (int i=0;i<10;i++){
                arrPtr++;
                cout<<"arrPtr ["<<i<<"]\t"<<*arrPtr<<endl;
        }
        cout<<endl;
        return 0; }

このプログラムをコンパイルすると

g ++ main.cpp -o main && ./main

それは私に与えます

arrPtr [0] 2
arrPtr [1] 4
arrPtr [2] 6
arrPtr [3] 0
arrPtr [4] 135145
arrPtr [5] 0
arrPtr [6] 0
arrPtr [7] 0
arrPtr [8] 0
arrPtr [9] 0

arrPtrが「有効な」要素を指していないことを検出(スローまたはチェック)できるようにしたい。上記のコードでは、最後の有効な要素はarrPtr[3]です。

「私も」と答えないでください!

4

4 に答える 4

5

を使用しvectorます。

int main()
{
    std::vector<int> a(4);

    for (size_t i = 0; i < 4; ++i)
        a[i] = i * 2;
    for (size_t i = 0; i < 10; ++i)
        std::cout << i << ": " << a.at(i) << std::endl;
}

結果:

0: 0
1: 2
2: 4
3: 6
terminate called after throwing an instance of 'std::out_of_range'
  what():  vector::_M_range_check
Aborted
于 2012-08-03T12:21:07.557 に答える
2

他の人は、この具体的な問題の解決策を示していますstd::vector。生のポインタの代わりに使用し(とにかくこれを実行してください!)、を介して要素にアクセスし.at()ます。

ただし、一般的には、コードで状況が発生しないことを確認する必要があります。範囲外のエラーは、実行時に処理する必要のある状況ではありません。コードのバグであり、事前に削除する必要があります。

そのためのいくつかの戦略があります-たとえば、インデックス付きアクセスを使用しないでください。このようなインスタンスのほとんどは、イテレータアクセスに置き換えることができます。これにより、自動的に安全ではありませんが、エラーが発生しにくくなります。

さらに良いことに、可能な限りループを避け、代わりにC++標準ライブラリの高次アルゴリズムを使用してください。

例として、ループのないコードは次のようになります。

std::vector<int> arr;
std::generate_n(std::back_inserter(arr), 4,
    [] {
        static int current = 0;
        return current++ * 2;
    });
std::copy(begin(arr), end(arr), std::ostream_iterator<int>(std::cout, "\n"));

このスタイルには多少の慣れが必要ですが、コードでエラーが発生する可能性が大幅に減少し、一部のエラークラスが適切に不可能になります。

于 2012-08-03T12:30:29.690 に答える
1

プレーンなCアレイでは不可能です。std :: vectorを使用できます。これには、境界チェックを使用した要素アクセス用のAPIがあります。

于 2012-08-03T12:19:32.623 に答える
0

このトピックは広く議論されています。一般に、C言語では、事前に配列の情報を知らなければ、ポインターが配列内の場所を指しているかどうかを検出することはできません。

@Charlie Martinがこの投稿への回答で述べたように、これは境界チェックに追加の操作が必要になるためです。Cは速度に敏感なプログラム(ハードウェアドライバーなど)を作成するために一般的に使用されるため、境界チェックは言語ではなく、それを必要とする人々によって実装されます。

したがって、境界チェックを実行する場合は、次のような操作を行う必要があります。

int *start = new int[4];
int size=4;
int *arrPtr;
...
for (int i=0,arrPtr=start;i<10;i++){
    arrPtr++;
    if(arrPtr>=start && arrPtr <start+size) // the boundary checking by yourself
       cout<<"arrPtr ["<<i<<"]\t"<<*arrPtr<<endl;
}

このようにして、言語を使用して、境界チェックを実行するために追加の操作を使用する価値があり、必要かどうかを判断できます。

そしてもちろん、プログラムで境界チェックが必要であると判断すると、などの高レベルのデータ型がすでに実装されていますvector

于 2012-08-03T12:55:20.087 に答える