web-dev-qa-db-ja.com

C ++でベクター要素へのポインターを返す

グローバルスコープにmyObjectsのベクターがあります。 std::vector<myObject>::const_iteratorを使用してベクトルをトラバースし、特定の要素を見つけるためにいくつかの比較を行うメソッドがあります。必要な要素が見つかったら、その要素へのポインタを返すことができます(ベクトルはグローバルスコープに存在します)。

&iteratorを返す場合、イテレータのアドレスまたはイテレータが指しているもののアドレスを返しますか?

const_iteratorをmyObjectにキャストして、そのアドレスを返す必要がありますか?

59
Krakkos

イテレータが指すもののアドレスを返します。

&(*iterator)

編集:混乱を解消するには:

vector <int> vec;          // a global vector of ints

void f() {
   vec.Push_back( 1 );    // add to the global vector
   vector <int>::iterator it = vec.begin();
   * it = 2;              // change what was 1 to 2
   int * p = &(*it);      // get pointer to first element
   * p = 3;               // change what was 2 to 3
}

ポインターのベクトルまたは動的割り振りの必要はありません。

84
anon

&iteratorを返すと、イテレーターのアドレスが返されます。要素を参照する方法を返したい場合は、イテレータ自体を返します。

イテレータ/ポインタを返すためにベクトルをグローバルにする必要はありませんが、ベクトル内の操作はイテレータを無効にできることに注意してください。たとえば、ベクトルに要素を追加すると、新しいsize()が予約メモリよりも大きい場合、ベクトル要素を別の位置に移動できます。ベクターから特定のアイテムの前に要素を削除すると、反復子は別の要素を参照します。

どちらの場合も、STLの実装によっては、ランダムエラーが頻繁に発生するため、デバッグが困難になる場合があります。

コメントの後の編集: 'はい、イテレータを返したくありませんでしたa)そのconst、およびb)確かにローカルの一時的なイテレータだけですか? – Krakkos '

反復子は、他の変数よりもローカルまたは一時的ではなく、コピー可能です。あなたはそれを返すことができ、コンパイラはポインタを使用する場合と同じようにコピーを作成します。

これで、const-nessが追加されました。呼び出し元が返された要素(ポインタまたはイテレータ)を介して変更を実行する場合は、非定数イテレータを使用する必要があります。 (イテレータの定義から「const_」を削除するだけです)。

イテレータを返すことはお勧めできません。反復子は、ベクトルの変更(反転\削除)が発生すると無効になります。また、イテレータはスタック上に作成されたローカルオブジェクトであるため、同じアドレスを返すことはまったく安全ではありません。ベクトル反復子ではなくmyObjectを使用することをお勧めします。

EDIT:オブジェクトが軽量の場合、オブジェクト自体を返す方が良いです。それ以外の場合は、ベクターに格納されているmyObjectへのポインターを返します。

3
aJ.

ベクターがグローバルスコープ内にある限り、以下を返すことができます。

&(*iterator)

これは一般的にかなり危険であることに注意してください。ベクターがグローバルスコープから外れて破壊された場合、myObjectへのポインターは無効になります。これらの関数をより大きなプロジェクトの一部として作成している場合、非constポインターを返すと、戻り値が削除される可能性があります。これは、アプリケーションに対して未定義の壊滅的な影響を及ぼします。

これを次のように書き換えます。

myObject myFunction(const vector<myObject>& objects)
{
    // find the object in question and return a copy
    return *iterator;
}

返されたmyObjectを変更する必要がある場合は、値をポインターとして保存し、ヒープに割り当てます。

myObject* myFunction(const vector<myObject*>& objects)
{
    return *iterator;
}

そうすることで、いつ破壊されるかを制御できます。

このような何かはあなたのアプリを壊します:

g_vector<tmpClass> myVector;

    tmpClass t;
    t.i = 30;
    myVector.Push_back(t);

    // my function returns a pointer to a value in myVector
    std::auto_ptr<tmpClass> t2(myFunction());
3
Aaron Saarela

ベクトルのdata関数を使用できます。

ベクトルの最初の要素へのポインターを返します。

最初の要素へのポインタではなく、インデックスが必要な場合は、たとえば次のようにすることができます。

//the index to the element that you want to receive its pointer:
int i = n; //(n is whatever integer you want)

std::vector<myObject> vec;
myObject* ptr_to_first = vec.data();

//or

std::vector<myObject>* vec;
myObject* ptr_to_first = vec->data();

//then

myObject element = ptr_to_first[i]; //element at index i
myObject* ptr_to_element = &element;
1
user2133061

MyObjectのコピーをベクターに保存しています。したがって、myObjectのインスタンスをコピーするのは、コストのかかる操作ではないと思います。そして、最も安全なのは、関数からmyObjectのコピーを返すことだと思います。

0
Naveen

たとえば、次のものがあるとします。

_std::vector<myObject>::const_iterator first = vObj.begin();
_

次に、ベクターの最初のオブジェクトは_*first_です。アドレスを取得するには、&(*first)を使用します。

ただし、STLの設計に合わせて、後でSTLアルゴリズムに渡す場合は、代わりにイテレータを返すことをお勧めします。

0
dirkgently

Dirkgentlyとanonの答えを参照して、begin関数の代わりにfront関数を呼び出すことができますので、not*を記述する必要がありますが、&のみを記述する必要があります。

コード例:

vector<myObject> vec; //You have a vector of your objects
myObject first = vec.front(); //returns reference, not iterator, to the first object in the vector so you had only to write the data type in the generic of your vector, i.e. myObject, and not all the iterator stuff and the vector again and :: of course
myObject* pointer_to_first_object = &first; //* between & and first is not there anymore, first is already the first object, not iterator to it.
0
user2133061

イテレータが指すもののアドレスを返す必要があるかどうかはわかりません。必要なのは、ポインター自体です。この目的で_Ptrの使用を実装するSTLのイテレータークラス自体が表示されます。だから、ただやる:

return iterator._Ptr;
0
arviman