Saya baru mengenal bahasa C ++. Saya telah mulai menggunakan vektor, dan telah memperhatikan bahwa di semua kode yang saya lihat untuk iterasi meskipun vektor melalui indeks, parameter pertama dari for
loop selalu sesuatu berdasarkan vektor. Di Java saya mungkin melakukan sesuatu seperti ini dengan ArrayList:
for(int i=0; i < vector.size(); i++){
vector[i].doSomething();
}
Apakah ada alasan mengapa saya tidak melihat ini di C ++? Apakah ini praktik yang buruk?
c++
coding-style
for-loop
iterator
Flynn
sumber
sumber
std::vector<int>::size_type i = 0;
, atau mungkinstd::vector<int>::iterator it = vector.begin();
?std::vector
? , sebenarnya Q yang ditanyakan di sini adalah: Apakah ada alasan mengapa saya tidak melihat ini di C ++? Apakah ini praktik yang buruk? alias Mengapa saya selalu melihat kode dalam C ++ yang menggunakan iterator saat melakukan iterasistd::vector
?Jawaban:
Tidak. Ini bukan praktik yang buruk, tetapi pendekatan berikut membuat kode Anda memiliki fleksibilitas tertentu .
Biasanya, kode pra-C ++ 11 untuk iterasi elemen kontainer menggunakan iterator, seperti:
std::vector<int>::iterator it = vector.begin();
Ini karena membuat kode lebih fleksibel.
Semua wadah perpustakaan standar mendukung dan menyediakan iterator. Jika di kemudian hari Anda perlu beralih ke penampung lain, kode ini tidak perlu diubah.
Catatan: Menulis kode yang berfungsi dengan setiap kemungkinan penampung pustaka standar tidak semudah kelihatannya.
sumber
auto
.Alasan mengapa Anda tidak melihat praktik semacam itu cukup subjektif dan tidak dapat memiliki jawaban yang pasti, karena saya telah melihat banyak kode yang menggunakan cara yang Anda sebutkan daripada
iterator
kode gaya.Berikut ini bisa menjadi alasan orang tidak mempertimbangkan
vector.size()
cara perulangan:size()
setiap kali dalam kondisi loop. Namun entah itu bukan masalah atau bisa diperbaiki sepelestd::for_each()
atasfor
lingkaran itu sendiristd::vector
lain (misalnyamap
,list
) juga akan menuntut perubahan mekanisme perulangan, karena tidak setiap wadah mendukungsize()
gaya perulanganC ++ 11 menyediakan fasilitas yang baik untuk bergerak melalui kontainer. Itu disebut "range based for loop" (atau "Enhanced for loop" di Java).
Dengan sedikit kode Anda dapat melintasi sepenuhnya (wajib!)
std::vector
:vector<int> vi; ... for(int i : vi) cout << "i = " << i << endl;
sumber
#pragma omp parallel for
.Cara paling bersih untuk melakukan iterasi melalui vektor adalah melalui iterator:
for (auto it = begin (vector); it != end (vector); ++it) { it->doSomething (); }
atau (setara dengan yang di atas)
for (auto & element : vector) { element.doSomething (); }
Sebelum C ++ 0x, Anda harus mengganti auto dengan tipe iterator dan menggunakan fungsi anggota alih-alih fungsi global dimulai dan diakhiri.
Ini mungkin yang Anda lihat. Dibandingkan dengan pendekatan yang Anda sebutkan, keuntungannya adalah Anda tidak terlalu bergantung pada jenisnya
vector
. Jika Anda mengubahvector
ke kelas "tipe-koleksi" yang berbeda, kode Anda mungkin masih berfungsi. Namun, Anda juga dapat melakukan hal serupa di Java. Tidak banyak perbedaan secara konseptual; C ++, bagaimanapun, menggunakan template untuk mengimplementasikan ini (dibandingkan dengan generik di Java); karenanya pendekatan ini akan bekerja untuk semua tipe yangbegin
danend
fungsinya ditentukan, bahkan untuk tipe non-kelas seperti array statis. Lihat di sini: Bagaimana cara kerja berbasis rentang untuk array biasa?sumber
begin
danend
, bagaimanapun, adalah satu baris.auto
di sisi lain akan cukup rumit.Cara yang benar untuk melakukannya adalah:
for(std::vector<T>::iterator it = v.begin(); it != v.end(); ++it) { it->doSomething(); }
Dimana T adalah tipe kelas di dalam vektor. Misalnya jika kelasnya adalah CActivity, tulis saja CActivity, bukan T.
Jenis metode ini akan bekerja pada setiap STL (Tidak hanya vektor, yang sedikit lebih baik).
Jika Anda masih ingin menggunakan indeks, caranya adalah:
for(std::vector<T>::size_type i = 0; i != v.size(); i++) { v[i].doSomething(); }
sumber
std::vector<T>::size_type
selalusize_t
? Itulah tipe yang selalu saya gunakan untuk itu.Ada beberapa alasan kuat untuk menggunakan iterator, beberapa di antaranya disebutkan di sini:
Beralih penampung nanti tidak membuat kode Anda tidak valid.
misalnya, jika Anda beralih dari std :: vector ke std :: list, atau std :: set, Anda tidak dapat menggunakan indeks numerik untuk mendapatkan nilai yang Anda masukkan. Penggunaan iterator masih valid.
Penangkapan waktu proses dari iterasi yang tidak valid
Jika Anda memodifikasi penampung Anda di tengah-tengah loop Anda, saat Anda menggunakan iterator Anda, itu akan memunculkan pengecualian iterator yang tidak valid.
sumber
Saya terkejut tidak ada yang menyebutkan bahwa iterasi melalui array dengan indeks integer memudahkan Anda untuk menulis kode yang salah dengan memasukkan array dengan indeks yang salah. Misalnya, jika Anda memiliki loop bersarang yang menggunakan
i
danj
sebagai indeks, Anda mungkin salah meng-subskrip sebuah array denganj
daripadai
dan dengan demikian memperkenalkan kesalahan ke dalam program.Sebaliknya, bentuk lain yang tercantum di sini, yaitu
for
loop berbasis rentang , dan iterator, jauh lebih rentan terhadap kesalahan. Semantik bahasa dan mekanisme pemeriksaan jenis kompiler akan mencegah Anda mengakses larik secara tidak sengaja menggunakan indeks yang salah.sumber
Dengan STL, pemrogram menggunakan
iterators
untuk melintasi melalui kontainer, karena iterator adalah konsep abstrak, diimplementasikan di semua kontainer standar. Misalnyastd::list
tidak punyaoperator []
sama sekali.sumber
Menggunakan operator otomatis sangat memudahkan penggunaan karena seseorang tidak perlu khawatir tentang tipe data dan ukuran vektor atau struktur data lainnya.
Iterasi vektor menggunakan auto dan for loop
vector<int> vec = {1,2,3,4,5} for(auto itr : vec) cout << itr << " ";
Keluaran:
1 2 3 4 5
Anda juga dapat menggunakan metode ini untuk mengulang set dan daftar. Menggunakan auto secara otomatis mendeteksi tipe data yang digunakan dalam template dan memungkinkan Anda menggunakannya. Jadi, meskipun kita memiliki salah
vector
satustring
atauchar
sintaks yang sama akan bekerja dengan baiksumber
Cara yang benar untuk mengulang loop dan mencetak nilainya adalah sebagai berikut:
#include<vector> //declare the vector of type int vector<int> v; //insert the 5 element in the vector for ( unsigned int i = 0; i < 5; i++){ v.push_back(i); } //print those element for (auto it = 0; it < v.end(); i++){ std::cout << *it << std::endl; }
sumber
Berikut adalah cara yang lebih sederhana untuk mengulang dan mencetak nilai dalam vektor.
for(int x: A) // for integer x in vector A cout<< x <<" ";
sumber
//different declaration type vector<int>v; vector<int>v2(5,30); //size is 5 and fill up with 30 vector<int>v3={10,20,30}; //From C++11 and onwards for(auto itr:v2) cout<<"\n"<<itr; //(pre c++11) for(auto itr=v3.begin(); itr !=v3.end(); itr++) cout<<"\n"<<*itr;
sumber
Jika Anda menggunakan
std::vector<std::reference_wrapper<std::string>> names{ };
Jangan lupa, ketika Anda menggunakan auto in the for loop, untuk menggunakan juga get, seperti ini:
for (auto element in : names) { element.get()//do something }
sumber