C ++ STL Vektor: Dapatkan iterator dari index?


200

Jadi, saya menulis banyak kode yang mengakses elemen dalam vektor stl dengan indeks [], tapi sekarang saya perlu menyalin hanya sepotong vektor. Sepertinya vector.insert(pos, first, last)fungsi yang saya inginkan ... kecuali saya hanya punya pertama dan terakhir sebagai int. Apakah ada cara yang baik saya bisa mendapatkan iterator dengan nilai-nilai ini?



Jika saya tidak salah, tidak ada jawaban yang memeriksa batas, yang mungkin menjadi masalah. Secara khusus, std :: advance docs mengatakan perilaku tidak terdefinisi jika Anda menggunakannya untuk melewati batas wadah yang mendasarinya.
Martin Pecka

Jawaban:


293

Coba ini:

vector<Type>::iterator nth = v.begin() + index;

4
Secara umum, Anda dapat menggunakan aritmatika yang sama dengan iterator STL daripada dengan pointer. Mereka dirancang untuk dapat ditukar ketika menggunakan algoritma STL.
Vincent Robert

18
@VincentRobert: Sebaliknya. Pointer adalah implementasi valid dari acak iterator STL, kategori paling kuat. Tapi yang lain, kategori yang kurang kuat seperti forward iterators tidak mendukung aritmatika yang sama.
MSalters

6
Saya ingin menambahkan lima sen untuk jawaban ini dan merekomendasikanstd::next(v.begin(), index)
stryku

87

cara yang disebutkan oleh @ sangat ( v.begin() + index )bagus dan cepat untuk vektor

tetapi cara yang paling umum dan untuk iterator akses acak bekerja waktu konstan juga. std::advance( v.begin(), index )


Perbedaan penggunaan EDIT :

std::vector<>::iterator it = ( v.begin() + index );

atau

std::vector<>::iterator it = v.begin();
std::advance( it, index );

ditambahkan setelah catatan @litb.


tidak std :: muka memerlukan iterator non-const sebagai argumen pertama?
goldPseudo

Anda dapat menggunakan std :: terlebih dahulu dengan const dan non-const iterator
Bayda

1
Anda seharusnya tidak mempercayai msvc dalam hal itu. ia memiliki ekstensi non-standar yang membuatnya menerima hal semacam ini, namun semua kompiler lain berperilaku standar dan menolaknya.
Johannes Schaub - litb

1
Saya pikir masalahnya adalah kebingungan tentang arti "const": advance () dengan senang hati akan bekerja pada const_iterator <T>, yang merupakan iterator yang bisa berubah yang mengacu pada elemen const dari tipe T; itu tidak akan bekerja pada objek iterator yang merupakan const (yaitu "const iterator <T>" atau "iterator <T> const").
j_random_hacker

7
Jika Anda tahu bahwa Anda sedang berurusan dengan std::vector, tidak ada gunanya menggunakan std::advance. Ini hanya memikat Anda untuk berpikir Anda sedang menulis kode container-agnostik (yang tidak Anda lakukan, memikirkan aturan pembatalan iterator, kompleksitas runtime yang berbeda dan yang lainnya). Satu-satunya kasus ketika std::advancemasuk akal adalah ketika Anda menulis template sendiri yang tidak tahu jenis iterator yang berurusan dengannya.
Frerich Raabe

47

Juga; auto it = std::next(v.begin(), index);

Pembaruan: Membutuhkan kompiler yang memenuhi persyaratan C ++ 11x


2
Perlu dicatat bahwa ini adalah cara C ++ 11! std :: selanjutnya setara dengan std :: muka. Menggunakan fungsi-fungsi ini daripada menggunakan aritmatika membuat bertukar jenis wadah jauh lebih mudah. Bahkan bekerja pada afaik c-array, seperti std :: begin dan std :: end.
Zoomulator

2
Juga harus dicatat bahwa std :: advance dirancang oleh orang idiot karena menggunakan referensi sebagai output, dan bukan nilai pengembalian.
Viktor Sehr

1
for (auto it = begin (c); it! = end (c); advance (it, n)) {...}
Zoomulator

2
Keduanya memiliki kegunaannya. stda :: advance berguna untuk mengubah iterator pada tempatnya. Ini masalah kinerja dalam loop. Saya lebih suka berikutnya dalam hal penugasan, seperti yang Anda sarankan. Saya baru saja menemukannya agak keras mengklaimnya sebagai idiot. Kedua fungsi dirancang dengan situasi yang berbeda dalam pikiran, meskipun pada dasarnya keduanya sama.
Zoomulator

5
@Zoomulator: Jika menyalin iterator Anda adalah masalah kinerja, Anda memiliki masalah yang lebih besar untuk dihadapi.
Mooing Duck


-3

Sebenarnya std :: vector dimaksudkan untuk digunakan sebagai tab C saat dibutuhkan. (C ++ permintaan standar untuk implementasi vektor, sejauh yang saya tahu - penggantian untuk array di Wikipedia ) Sebagai contoh, adalah sah untuk melakukan hal ini, menurut saya:

int main()
{

void foo(const char *);

sdt::vector<char> vec;
vec.push_back('h');
vec.push_back('e');
vec.push_back('l');
vec.push_back('l');
vec.push_back('o');
vec.push_back('/0');

foo(&vec[0]);
}

Tentu saja, baik foo tidak boleh menyalin alamat yang dilewatkan sebagai parameter dan menyimpannya di suatu tempat, atau Anda harus memastikan dalam program Anda untuk tidak pernah mendorong item baru dalam vec, atau meminta untuk mengubah kapasitasnya. Atau kesalahan segmentasi risiko ...

Karena itu dalam contoh Anda itu mengarah ke

vector.insert(pos, &vec[first_index], &vec[last_index]);

Membuat saya bertanya-tanya mengapa mereka memutuskan untuk abstrak ke iterator jika mereka hanya petunjuk ... mereka pada dasarnya "menyembunyikan" kemampuan ini.
mpen

Untuk konsistensi? Karena itu akan memungkinkan Anda untuk dengan mudah menghapus instance vektor untuk setiap jenis wadah lain dalam kode Anda.
Yves Baumes

4
& vec [i] menghasilkan pointer yang belum tentu kompatibel dengan vektor <> :: iterator. vec.begin () + i masih memiliki manfaat menjadi apa pun iterator yang didefinisikan oleh perpustakaan Anda - termasuk mencentang iterator dalam mode debug, misalnya. Jadi, jika Anda tidak memerlukan pointer (untuk I / O misalnya), Anda harus selalu memilih iterator.
sellibitze

@KerrekSB Dari 23.3.6.1 dalam konsep standar c ++: "Elemen-elemen vektor disimpan secara bersebelahan, artinya jika v adalah vektor <T, Allocator> di mana T adalah beberapa jenis selain bool, maka ia mematuhi identitas & v [ n] == & v [0] + n untuk semua 0 <= n <v.size () "
yves Baumes

2
@yvesBaumes: itu tidak ada hubungannya dengan iterator vektor. Namun, memang benar bahwa pointer telanjang juga merupakan iterator - mereka bukan vektor iterator.
Kerrek SB
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.