QStringの配列とQStringポインタがあるとしましょう。ポインタを使用して配列全体を反復処理したいと思います。私はこれを行うことができますか?
QString * strPointer;
QString data[100];
strPointer = & data[0]; //address to first element
strPointer ++; //address to second element
これは有効ですか、それとも私は何か間違ったことをしていますか?
あなたは正しい方向に進んでいます。これが1つの方法です
QString data[100];
for (QString* strPointer = &data[0]; strPointer != &data[100]; ++strPointer)
{
...
}
はい、ポインタのタイプが配列内で実際にポイントされているものと一致する限り、これは問題ありません。ポインタをインクリメントすることにより、ポインタ演算を実行しています。
標準ライブラリのイテレータは多くの点でポインタのように見えるように記述されており、すべての標準ライブラリアルゴリズムはテンプレートパラメータとして指定されたイテレータを使用するため、これらのアルゴリズムを次のように使用することは合法であり、明確に定義されています。生のポインタも。たとえば、これは、ポインタを使用しても完全に正当です。
const size_t num_data = sizeof(data)/sizeof(data[0]);
std::copy( &data[0], &data[num_data], ostream_iterator<QString>(cout,"\n") );
...もちろん、オブジェクトに対して実装operator<<
したと仮定しQString
ます。
さて、これがすべて言われているので、これを見てください:
QString data[100];
これがマジックナンバー100
と呼ばれるものです。マジックナンバーの使用は、アンチパターンまたは悪い習慣であると広く考えられています。いくつか質問してください。
可能な限り、マジックナンバーの使用は避けるのが最善です。ここでの選択100
は任意です。オブジェクトを追加および削除するときに拡大および縮小するコレクションタイプを使用することをお勧めします。 std::vector
始めるのに良い場所です:
std::vector<QString> data;
これで、アイテムを追加できます。
data.push_back( ... );
...それらを削除し、イテレータを使用して簡単に反復します。
std::copy( data.begin(), data.end(), ostream_iterator<QString>(cout,"\n") );
はい、そうです。インデックスのチェックについて覚えておいてください-operator++は配列を超えて「行き過ぎ」になる可能性があります。
はい、配列の要素へのポインターをインクリメントすると、次の要素または配列の終わりを1つ超えた位置へのポインターが生成されます。
整数型の式がポインターに加算またはポインターから減算されると、結果はポインターオペランドの型になります。ポインタオペランドが配列オブジェクトの要素を指し、配列が十分に大きい場合、結果は元の要素からオフセットされた要素を指し、結果の配列要素と元の配列要素の添え字の差が整数式に等しくなります。つまり、式Pが配列オブジェクトのi番目の要素を指している場合、式(P)+ N(同等にN +(P))および(P)-N(Nの値はn)はを指します。 、それぞれ、配列オブジェクトのi +n番目およびi− n番目の要素(存在する場合)。さらに、式Pが配列オブジェクトの最後の要素を指している場合、式(P)+1は配列オブジェクトの最後の要素の1つ先を指します。式Qが配列オブジェクトの最後の要素の1つ先を指している場合、式(Q)-1は配列オブジェクトの最後の要素を指します。ポインタオペランドと結果の両方が同じ配列オブジェクトの要素を指している場合、または配列オブジェクトの最後の要素を1つ過ぎている場合、評価によってオーバーフローが発生することはありません。それ以外の場合、動作は定義されていません。
— [expr.add] 5.7 / 5